Pass parameters to event handlers

Keywords: JQuery

Pass parameters to event handlers

Today, the task of brushing Baidu Front-end College has encountered a problem, which needs to pass parameters to the event handler function. I abstract the problem into the following questions:

var lis = document.getElementsByTagName('li');
for(var i=0; i<lis.length; i++){
  this.i=i;
  btn.addEventListener('click',handler.bind(this));
}
//i want to get i in the event handler.
function handler(e){
    this.i;
}

The bind() solution in ES5:

The solution is to bind the context of the event handler to this in the for loop; the context of the event handler is not a btn object;

After analyzing the principle, we first study the bind function in detail.
The bind function binds the current function to the specified object, returns a new function, and when the new function is called, the code executes in the context of the specified object.
The grammar is:

Bar. bind (context parameter, common parameter 1, common parameter 2,... Ordinary parameters are passed into the bar function.

It is solved by the $. proxy() method in jQuery.

jQuery.proxy(), accepts a function, then returns a new function, and the new function always maintains a specific context.

jQuery.proxy( function, context )
function Functions that will change context.
context Contextual context of functions(this)Will be set to this object Object.

jQuery.proxy( context, name )
context The context of the function is set to this object object
name Function names that will change context(This function must be the previous parameter 'context' Object attributes)

This method is usually used when attaching an event handler to an element, where the context is actually directed to another object.

var obj = {
name: "John",
test: function() {
alert( this.name );
$("#test").unbind("click", obj.test);
}
};

$("#test").click( jQuery.proxy( obj, "test" ) );


// The following code is equivalent to the above sentence:
// $("#test").click( jQuery.proxy( obj.test, obj ) );


// It can be compared with executing the following sentence separately.
// $("#test").click( obj.test );

jQuery source proxy:
Use the apply form to execute the callback function.

jQuery.proxy = function( fn, proxy, thisObject ) {
    if ( arguments.length === 2 ) {
        // jQuery.proxy(context, name);
        if ( typeof proxy === "string" ) {
            thisObject = fn;
            fn = thisObject[ proxy ];
            proxy = undefined;


            /* The results of transformation were as follows:
                thisObject -> context
                fn -> name
                proxy -> undefined
             */
        }
        // jQuery.proxy(name, context);
        else if ( proxy && !jQuery.isFunction( proxy ) ) {
            thisObject = proxy;
            proxy = undefined;
        }
    }
    if ( !proxy && fn ) {
        /* When using proxy to guarantee function execution, context is the specified value */
        proxy = function() {
            return fn.apply( thisObject || this, arguments );
        };
    }
    // Set the guid of unique handler to the same of original handler, so it can be removed
    if ( fn ) {
        proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
    }
    // So proxy can be declared as an argument
    return proxy;
}

call and apply are commonly used, mostly as callbacks.

There is a problem with stack overflow. Examples are typical for reference.
For example, there are the following codes:

$('#myElement').click(function() {
        // In this function, "this" is our DOM element.
    $(this).addClass('aNewClass');
});

Here this is our DOM element. If we had to wait a while before adding the class style, we might write the code as follows (note: problematic code)

$('#myElement').click(function() {
    setTimeout(function() {
          // Problem! In this function "this" is not our element!
        $(this).addClass('aNewClass');
    }, 1000);
});

this is not the DOM element we expected. The solution is to use jQuery's $. proxy(), code as follows:

$('#myElement').click(function() {
   // give $.proxy our function,
    setTimeout($.proxy(function() {
        $(this).addClass('aNewClass');  // Now "this" is again our element
    }, this), 1000);
   // and tell it that we want our DOM element to be the value of "this" in the function
});

We can understand the above code in this way:

function() {
    // func is the function we gave to $.proxy
    func.apply( ctx );
    //  ctx is the value we wanted for "this" (our DOM element)
}

This shows the powerful effect of $. proxy() in jQuery.

Note: In jQuery 1.6 and later, in addition to the two usages mentioned above, proxy adds two other usages:

jQuery.proxy( function, context [, additionalArguments ] )
jQuery.proxy( context, name [, additionalArguments ] )

Posted by LuiePL on Fri, 28 Jun 2019 15:30:10 -0700