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.
-
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 adiv
it will fire the events this waybody - 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 (theimg
in this case) it providesevent.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 documentationAnd finally
currentTarget
is the element you attached the event, if we added the listener tobody
it’ll bebody
. So the arguments on each events arefire 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.
-
$.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
). Thethis
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 itsthis
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.