2011-06-18 42 views
2

這一直困擾着我。看看下面的代碼:保存分配給實例方法的變量的上下文

function tSt(val) { 
    this.val = val; 
} 

tSt.func = function(x) { 
    return x * 2; 
} 

tSt.prototype.func = function() { 
    return tSt.func(this.val); 
} 

var tmp = new tSt(5); 

console.log(tmp.func()); // 10 

var other = tmp.func; 

console.log(other()); // undefined 

我希望能夠做到這一點的原因是類似以下情形:

(function(funcarr) { 
    for (var i = 0; i < funcarr.length; i++) 
     console.log(funcarr[i]()); 
})([ tmp.func ]); 

這又如何實現呢?

更新:

這裏有一個潛在的更具全球性的解決辦法,但我不知道是否有任何缺點做這種方式:

​​

回答

3

使用Function#bind

var other = tmp.func.bind(tmp); 

這確保了每當調用other時,this指針將tmp

由於bind未在所有瀏覽器中實現,因此您可能需要使用上面鏈接中給出的填充。 (事實上​​,我建議你去所有的方式,並得到一個ES5 shim


如果你願意放棄原型繼承,如果你想通過周圍方法,而忘記了bind他們這是必要的,然後,我反而建議module pattern

function TSt(val) { 
    // save a reference to our current "this" so that, even inside of methods 
    // called from other contexts, we still have it. 
    var that = this; 

    that.val = val; 
    that.func = function() { 
     return that.val * 2; 
     // Since we're using that instead of this, still works even without bind. 
    } 
} 

var tmp = new TSt(5); 
var other = tmp.func; 
console.log(other()); // 10 

事實上,這種模式的另一大好處是,你可以得到私有變量:

function Encapsulated(mine, public) { 
    var that = this; 

    var private = mine * 2; 

    that.public = public; 
    that.compute = function() { 
     return that.public * private; 
    }; 
} 

現在,Encapsulated實例的消費者無法訪問mineprivate,但只能訪問public

+0

哇,那很快。該解決方案有效。介意看看我的更新並讓我知道你的想法? –

+0

已更新的示例有效,但它失去了原型繼承的好處,因爲現在您正在爲每個'tSt'實例創建一個單獨的'func'屬性。 'func'恰好與'tSt.prototype.func'有關,但這真的不相關,因爲沒有調用者會看到原型繼承的'func',只是你的新實例特有的。換句話說,你的代碼和'this.func =(function(x){return x * 2})。bind(this);'是一樣的。 – Domenic

+0

有意義,但如果我希望能夠簡單地將'other.func'作爲函數參數而不是'other.func.bind(tmp)'來傳遞,那麼就有必要放棄這個好處。謝謝您的幫助。 –