奇怪的$ .each行为

时间:2014-10-29 17:17:24

标签: javascript jquery scope this

请考虑以下示例:

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);
});

这两个都按预期工作:this引用传入的集合中当前引用的对象。

但是,下一个例子真的很奇怪。

var z = [null];
$.each(z, function(){
    console.log(this);
});

在此示例中,您会注意到window已记录到控制台。

为什么会这样?

通过更明确的参数化可以很容易地解决这个问题:

$.each(z, function(key, value){
    console.log(value);
}); 

但我特别好奇为什么this在前一个例子中引用window

2 个答案:

答案 0 :(得分:2)

查看$.each的来源,您会看到这里发生了什么。

for (; i < length; i++) {
    value = callback.call(obj[i], i, obj[i]);

    if (value === false) {
        break;
    }
}

来自:http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.each

jQuery使用.call()来触发你的回调函数。根据Mozilla的.call文档:

  

请注意,可能不是该方法看到的实际值:如果该方法是non-strict mode代码中的函数, null 将替换为全局对象,原始值将被加框。

来自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

答案 1 :(得分:1)

来自文档:jQuery.each() documentation

  

$ .each()函数与$(selector).each()不同,即   用于独占迭代jQuery对象。 $ .each()   函数可用于迭代任何集合,无论它是否为   对象或数组。在数组的情况下,回调传递给   数组索引和每次相应的数组值。

更重要的是:

  

(价值可以   也可以通过关键字进行访问,但Javascript将始终使用   将此值包装为Object,即使它是一个简单的字符串或   数值。)该方法返回其第一个参数,即该对象   被迭代了。

在我看来,因为它试图将null包装为一个对象,所以jQuery必须为你返回window

我总是建议在这些类型的循环中使用回调函数的value(第二个参数)而不是this

$.each(z, function(key, value){
    console.log(value);
});