2015-02-05 41 views
6

我试图更改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/

+0

'this'将永远是一个数字。 – Krishna 2015-02-05 15:05:48

回答

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设置的。

你可以$.proxy,或bind(),但最简单的方法就是使用一个变量

var self = this; 

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

谢谢你,只是我想知道 – filur 2015-02-05 15:10:32

+1

不客气! – adeneo 2015-02-05 15:11:51

3

有几种方法从外部

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

2为此

1)参考窗口)绑定函数到特定范围

$.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 
}); 
+1

完整答案!对于旧版本的浏览器,只是缺少jQuery的支持:$ .each([1,2,3],$ .proxy(function(){ console.log(this); //期望看到窗口对象 }这个));' – 2015-02-05 15:12:28

3

只要使用Function.bind上回调指定你想要的功能在运行什么情况。

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

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