javascript closure: implicit parameters, caller-Collection of common programming errors

I need some clarification with javascript call’s metadata. Provided code below has SenderAsParameterFunc and NoExplicitParametersFunc which are being called from AnotherFunction’s each loops.

var Obj = function(){

Obj.SenderAsParameterFunc = function(sender, param1, param2){
// log $(sender).id;
}

Obj.NoExplicitParametersFunc = function(){

 // EXTRACT DEFAULT SENDER/CALLEE
 // I see in console Obj.NoExplicitParametersFunc.caller.arguments >> SEE REF1
}

 Obj.NoExplicitParametersFuncWithExtraArgs = function(this, par1, par2){
 // 'this' from each loop?
}

Obj.AnotherFunc = function(){

    var X = $('myselect');

    var par1 = 1;
    var par2 = 'bla';
    $.each(X.find("option"), function () {
                Obj.SenderAsParameterFunc(this, par1, par2); 
                // 'this' here references current object from 'each' loop
            });

    $.each(X.find("option"), Obj.NoExplicitParametersFunc); 
   // must be equvalent to first var, 
   // but to extract 'inner' this we have to do more magic in NoExplicitParametersFunc...

    var par1 = 1;
    var par2 = 'bla';
    $.each(X.find("option"), Obj.NoExplicitParametersFuncWithExtraArgs);
    }

}

So WHAT should be written in NoExplicitParametersFunc to get access to each option as that is done in SenderAsParameterFunc with $(this)?

==========

OK, TO Summarize what I’ve learned: if a function goes without parameters

$.each(X.find("option"), Obj.NoExplicitParametersFunc);

then ‘this’ is passed by default and is accessible within a function.

If a function has parameters

$.each(X.find("option"), function () { Obj.SenderAsParameterFunc(this, par1, par2); });

then ‘this’ MUST be included as a parameter (first?) to be accessible within the function.

=============

REF1:

b.Event
altKey: undefined
attrChange: undefined
attrName: undefined
bubbles: true
cancelable: false
ctrlKey: undefined
currentTarget: input#inputId
data: undefined
delegateTarget: input#inputId
eventPhase: 2
handleObj: Object
isDefaultPrevented: function ot(){return!1}
jQuery19105656534675508738: true
metaKey: false
originalEvent: Event
relatedNode: undefined
relatedTarget: undefined
shiftKey: undefined
srcElement: input#inputId
target: input#inputId
timeStamp: 1366622725473
type: "change"
view: undefined
which: undefined
__proto__: Object,

currentTarget, delegateTarget, srcElement, target ARE same, but what should be actually used, the most correct way? References would be appreciated!

Thanks.

  1. TL;DR: In your case it doesn’t matter, but if you are in doubt use currentTarget

    I don’t really understand your first question, but about the second one…

    When an event is dispatched usually this event bubbles, for example on this page:

    
      
        
      
    
    

    If the user clicks a img element inside a div it will fire the events this way

    body - capturing
    div - capturing
    img - at target
    div - bubbling
    body - bubbling
    

    So you can add a listener to body and you’ll catch the event. But to allow you to know which element was ACTUALLY clicked (the img in this case) it provides event.target property (srcElement on Internet Explorer).

    delegateTarget is a property added by jQuery and it provides extra info if you use event delegation. I don’t know exactly what it is but you can take a look at the documentation

    And finally currentTarget is the element you attached the event, if we added the listener to body it’ll be body. So the arguments on each events are

    fire body.click with { target: img, currentTarget: body }
    fire div.click  with { target: img, currentTarget: div  }
    fire img.click  with { target: img, currentTarget: img  }
    fire div.click  with { target: img, currentTarget: div  }
    fire body.click with { target: img, currentTarget: body }
    

    Depending on what you are doing you will need one or the other property.

  2. $.each(X.find("option"), function () {
          Obj.SenderAsParameterFunc(this);
          // 'this' here references anonymous function, 
          // from which it was called, so 'this' is sender
    });
    

    No. The anonymous function is not referenced by anything here (it is accessible as a parameter only in $.each). The this keyword in the callbacks of $.each does reference the iterated items. That also does answer your question:

    Obj.NoExplicitParametersFunc = function(i, v){
        console.log(this, i, v);
    }
    

    If a function has parameters [and is called in an anonymous function expression] then ‘this’ MUST be included as a parameter (first?) to be accessible within the function.

    Yes, as this is unique to each function call you have to pass its value along – just like you cannot just access local variables of your caller function, you cannot access its this value. To call the function with a specific this-value, you can use .call:

    $.each(X.find("option"), function(i, v) {
        Obj.SenderAsParameterFunc.call(this, i, v, par1, par2);
    });
    

Originally posted 2013-11-09 23:11:08.