2

当我开始使用 Javascript 时,我学到了当你传递一个外部事件处理程序(如计时器)对对象中函数的引用时的艰难方法,你不能依赖this.引用你的对象 - 它会而是指任何触发事件的范围(在计时器的情况下,我认为它是window?)。

我看到正在使用的解决方法是为自己创建一个私有/本地引用并在回调逻辑中使用它。例如:

function MyObject() { 
  var myThis = this;
  this.foo = true; 
  this.callback = function() { return myThis.foo; }
  this.interval = 30;
  setInterval(function () { myThis.callback(); }, myThis.interval);
}

对于这种情况,这是标准的编码实践吗?如果不是,首选的替代方案是什么以及为什么(例如,上述示例的风险是什么)?

4

3 回答 3

4

一个现代的替代方案是使用Function.prototype.bind()...

setInterval(this.callback.bind(this), this.interval);

.bind()方法返回一个函数,其this值绑定到您提供的第一个参数(在本例中为封闭this值)

它避免了需要this从嵌套函数的变量范围内引用封闭变量范围的变量中的所需值(如您的问题所示),从而提供更简洁的代码。


您可以在MDN旧实现中找到足以满足大多数情况的兼容性补丁。


旁注,thisJavaScript 中的值问题不是范围问题,而是调用上下文问题。

于 2012-04-06T01:25:22.700 回答
3

简短回答:这是一种公认​​的做法,据我所知,没有任何缺点。

长(ish)答案:您可以操纵 Prototype 方法来执行此操作,请参阅am not i am的答案。

于 2012-04-06T01:27:29.740 回答
1

您可以在不使用临时“this”的情况下执行此操作,也可以通过使用闭包而不使用绑定。

这在实践中并不是一个好方法,而是说明了闭包和绑定上下文是如何工作的。如果你能理解为什么会这样,那么你应该能够看到如何编写代码function.prototype.bind来做同样的事情。

http://jsfiddle.net/WRJqF/

function MyObject() { 
    this.foo = true; 
    this.callback = function() { 
        // firebug
        console.log( this.foo); 
    };
    this.interval = 30;

    setTimeout((function (that) {
        return function() {
            that.callback();
       };
   }(this)), this.interval); 

}

这使用了两个你会经常使用的 javascript 概念。

1 - 自执行功能。通过将函数包装在括号中,它会立即运行,并被有效地替换为其返回值,例如

(function add(x,y) {
    return x+y;
}(2,3)) 

变成6.

在上面的示例中,我们使用了一个自执行函数并this作为参数传递。这会创建一个闭包,并且参数的值(that只是为了让您感到困惑)与该函数永久关联。

2 - 用作第一类对象。this由于您可以返回一个函数(或通常像使用任何其他值一样使用它们),您可以从您的自执行函数中返回一个函数,该函数与创建它的堆栈帧的值绑定。因此,自执行功能实际上是

function() {
    that.callback();
};

...但是“that”实际上是在创建函数时有效的“this”!

都知道了吗??

于 2012-04-06T02:24:16.753 回答