我对这是如何工作有点困惑,让我给你发一个示例代码:
someClass = function() {
this.a = 10;
this.Foo = function() {
console.log(this.a); // will output "10"
setTimeout(this.Bar, 1);
}
this.Bar = function() {
console.log(this.a); // undefined
}
}
var instance = new someClass();
instance.Foo();
我的理解是,如果从setTimeout(或其他一些"处理程序"类型的东西)中调用它,则函数栏中不会显示this.a。 解决这个问题的常见/正确方法是什么?
(我在Node.js btw中尝试这个)
谢谢。
答案 0 :(得分:2)
当将函数 this.Bar 作为参数传递给另一个函数时,您需要绑定 this.Bar 到您的上下文d喜欢用它来执行。
如果你正在使用像jQuery或Underscore.js这样的JS库,他们已经拥有了这个功能:
setTimeout(_.bind(this.Bar, this), 1);
以下是 bind 函数的简单实现:
var bind = function(scope, fn) {
return function() {
return fn.apply(scope, arguments);
};
}
<强>更新强>:
正如@generalhenry指出的那样,node.js已经在( Function.prototype.bind )中附带了一个 bind 函数,所以你可以在不添加自定义的情况下执行此操作 bind 函数也不是外部库:
setTimeout(this.Bar.bind(this), 1);
答案 1 :(得分:2)
问题是当您将函数传递给this
时范围(setTimeout
)会丢失。
这是修复它的最简单方法,通过闭包存储this
作为参考,然后使用它。
// This uses _me_ everywhere for consistency, but the only place that really needs it
// is within the Bar method. But consistency in this case makes your code more change-
// proof, say if someone calls setTimeout(instance.Foo, 1)
someClass = function() {
var me = this;
me.a = 10;
me.Foo = function() {
console.log(me.a); // will output "10"
// setTimeout will cause me.Bar to be called with window as the context
setTimeout(me.Bar, 1);
}
me.Bar = function() {
// so we avoid using _this_ in here
console.log(me.a); // 10
}
}
更优雅的方法是使用Function.bind
someClass = function() {
this.a = 10;
this.Foo = function() {
console.log(this.a); // will output "10"
// the bind call will force it to use the first argument as `this`
setTimeout(this.Bar.bind(this), 1);
}
this.Bar = function() {
console.log(this.a); // undefined
}
}