更改$ .each()中的上下文

时间:2015-02-05 15:02:02

标签: javascript jquery

我正在尝试更改jQuery的$.each方法的上下文。我错过了什么?

$.each.call(this, [1,2,3], function(){
    console.log(this); // expecting to see the window object
});

var foo = { bar: 1 };
$.each.call(foo, [1,2,3], function(){
    console.log(this); // expecting to see the foo object
});

http://jsfiddle.net/53jhrbh5/

3 个答案:

答案 0 :(得分:5)

$.each在内部使用callapply在回调中设置正确的this值,类似于callback.apply(obj[i]),因此它使用数组作为this值,并使用call调用方法不会改变该值。

它的工作原理如下

function each(obj, callback, args) {
    var value, i = 0,
        length   = obj.length,
        isArray  = isArraylike(obj);

    if (args) {
        if (isArray) {
            for (; i < length; i++) {
                value = callback.apply(obj[i], args);
            }
        } else {
            for (i in obj) {
                value = callback.apply(obj[i], args);
            }
        }
    }
    return obj;
}

查看它如何调用回调,将传递的数组或对象中的每个值作为this值传递,这意味着您无法通过以不同方式调用$.each方法来更改它,如它的this值与回调函数的this值无关,该值由jQuery设置。

您可以$.proxybind()它,但简单的方法就是使用变量

var self = this;

$.each(arr, function() {
     console.log( self );
});

答案 1 :(得分:3)

有几种方法可以做到这一点

1)外面的参考窗口

var self = this;
$.each.call(this, [1,2,3], function(){
    console.log(self); // expecting to see the window object
});

2)将函数绑定到特定范围

$.each.call(this, [1,2,3], function(){
    console.log(this); // expecting to see the window object
}.bind(this));

3)使用绑定到当前上下文的ES6箭头功能(不能在大多数浏览器中使用而不进行6-> 5转换)

$.each.call(this, [1,2,3], () => {
   console.log(this); // expecting to see the window object
});

4)直接参考窗口

$.each.call(this, [1,2,3], () => {
   console.log(window); // expecting to see the window object
});

答案 2 :(得分:3)

只需在回调上使用Function.bind来指定您希望函数运行的上下文。

$.each([1,2,3], (function(){
    console.log(this); // expecting to see the window object
}).bind(this));

内部jQuery使用ThisBindingapplycall修饰符。因此,this始终为Number,除非您指定要运行的回调的上下文。