0

我对它的工作原理有点困惑,让我给你一个示例代码:

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

我的理解是 this.a 在函数 Bar 中不可见,如果它是从 setTimeout (或其他一些“处理程序”类型的东西)调用的。解决这个问题的常见/正确方法是什么?

(我在 Node.js 中尝试这个)

谢谢你。

4

2 回答 2

2

将函数this.Bar作为参数传递给另一个函数时,您需要将this.Bar绑定 到您希望执行它的上下文。

如果您使用 jQuery 或 Underscore.js 之类的 JS 库,它们已经具备该功能:

setTimeout(_.bind(this.Bar, this), 1);

这是绑定函数的简单实现:

var bind = function(scope, fn) {
  return function() {
    return fn.apply(scope, arguments);
  };
}

更新

正如@generalhenry 指出的那样,node.js 已经在(Function.prototype.bind )中附带了一个绑定函数,因此您可以在不添加自定义绑定函数或外部库的情况下执行此操作:

setTimeout(this.Bar.bind(this), 1);
于 2013-04-10T19:35:04.727 回答
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
    }
}
于 2013-04-10T19:37:24.160 回答