2013-08-24 140 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'之後,我的代碼中的設計問題在變量之間共享,所以我選擇了他的答案。 –