Reputation: 5565
Consider the following examples:
var x = [1, 2, 3];
$.each(x, function(){
console.log(this);
});
var o1 = {x:1, y:2};
var o2 = {a:1, b:2};
var o3 = {d:1, e:2}
var y = [o1, o2, o3];
$.each(y, function(){
console.log(this);
});
Both of these work as expected: this
refers to the currently referenced object from the collection passed in.
However, the next example is truly odd.
var z = [null];
$.each(z, function(){
console.log(this);
});
In this example, you'll notice that the window
is logged to the console.
Why is this the case?
It is easily remedied by doing more explicit parameterization like so:
$.each(z, function(key, value){
console.log(value);
});
But I'm particularly curious as to why this
refers to window
in the previous example.
Upvotes: 1
Views: 55
Reputation: 227310
Take a peek at the source for $.each
, and you will see what's going on here.
for (; i < length; i++) {
value = callback.call(obj[i], i, obj[i]);
if (value === false) {
break;
}
}
From: http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.each
jQuery is using .call()
to trigger your callback function. According to Mozilla's docs for .call
:
Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Upvotes: 2
Reputation: 67141
From the docs: jQuery.each() documentation
The $.each() function is not the same as $(selector).each(), which is used to iterate, exclusively, over a jQuery object. The $.each() function can be used to iterate over any collection, whether it is an object or an array. In the case of an array, the callback is passed an array index and a corresponding array value each time.
More importantly:
(The value can also be accessed through the this keyword, but Javascript will always wrap the this value as an Object even if it is a simple string or number value.) The method returns its first argument, the object that was iterated.
It looks to me like, since it is trying to wrap null
as an object, jQuery must return window
for you.
I would always suggest using the value
(2nd parameter) of the callback function instead of this
within these kinds of loops though.
$.each(z, function(key, value){
console.log(value);
});
Upvotes: 1