2013-08-24 94 views
2

我想创建一个具有自己范围的prototype函数。为此,我使用匿名函数,但我找不到访问对象成员的方法。以匿名函数访问此代码

这里是什么,我想实现一个简化版本:

function F() { 
    this.counter = 0; 
} 

F.prototype.increment = (function() { 
    var lastIncrementTime = -1; 
    var caller = this; // <--- it fails here because this is the Window object 
    return function(time) { 
     if (time > lastIncrementTime) { 
      caller.counter++; 
      lastIncrementTime = time; 
      return caller.counter; 
     } 
     return caller.counter; 
    } 
})(); 

f = new F(); 

f.increment(); 

我知道,因为这并不是指Ff对象失败。

有没有办法访问它?

回答

6

立即调用函数表达式(IIFE)本身只被调用一次,increment所有呼叫都将使用这些变量,因为他们是最后左,而不是重新var他们。

更改使用callapplybind

F.prototype.increment = (function() { 
    // this === F.prototype 
    // ... 
}).call(F.prototype); 

this在该示例上下文中不会实例特定调用上下文,但是原型。


好像你真正想要实现的东西有点不同,那就是你有一个独立的功能实例被创建时与它自己的关闭,初始化实例特定的属性。这些类型的操作可能消耗一点内存,因此不要存储太多的独特数据。

function F() { 
    this.counter = 0; 
    this.__init_increment(); // create `this.increment` 
} 
F.prototype.__init_increment = function() { 
    var lastIncrementTime = -1; 
    this.increment = function (time) { 
     if (time > lastIncrementTime) { 
      this.counter++; 
      lastIncrementTime = time; 
     } 
     return this.counter; 
    }; 
}; 
var f = new F(); 
f.increment(0); // 1 
f.increment(0); // 1 
f.increment(5); // 2 

在这个例子中,是this.increment对于每个实例,这意味着你必须为每个实例不同闭合不同功能。它们是由函数生成的原型,它设置实例属性。生成器不一定在原型中,只是在将其应用到实例时记住调用上下文。

+0

我想拥有特定于实例的计数器。 Kolink的版本似乎工作得很好,我明白在你的情况下,'this'将引用原型对象,它不适用于特定于实例的计数器,是吗? –

+2

@MadEchet如果你想要一些特定的实例,你可能希望它在_constructor_中,而不是在_prototype_中。 Kolink的解决方案“有效”,因为你使用的是'caller',你可以正常使用'this',但是这个解决方案仍然在所有实例中共享'lastIncrementTime'。 –

+0

的确如此,我没有意识到lastIncrementTime是共享的。谢谢! –

2

将您的var caller = this移动到匿名函数中,其中this将被正确设置。

+1

或者划掉'var called'行,并在返回的函数中使用'this'而不是'caller'。 – bfavaretto

+0

@Paul S.指出自从'lastIncrementTime'之后,我的代码中的设计问题在变量之间共享,所以我选择了他的答案。 –