我正在尝试更改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
});
答案 0 :(得分:5)
$.each
在内部使用call
和apply
在回调中设置正确的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 );
});
答案 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使用ThisBinding
,apply
等call
修饰符。因此,this
始终为Number
,除非您指定要运行的回调的上下文。