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对象。

有没有办法访问它?

4

2 回答 2

6

立即调用的函数表达式 (IIFE)本身只被调用一次,所有调用都increment将使用上次留下的变量,而不是重新使用var它们。

call使用,apply或更改调用上下文bind

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不同的函数,这意味着每个实例都有不同的闭包。它们由原型中的一个函数生成,该函数设置实例属性。生成器不必在原型中,只需记住将其应用于实例时的调用上下文即可。

于 2013-08-24T21:54:37.723 回答
2

将您var caller = this的匿名函数移入其中,该函数this已正确设置。

于 2013-08-24T21:47:16.753 回答