2014-09-28 67 views
0

也許標題聽起來有點不可思議(請改進) - 但我需要以下方案的解決方案。我有以下代碼:即使使用修改上下文的函數也不要修改上下文

var Foo = function() { 
    this._hello = "world!"; 
}; 

Foo.prototype.bar = function() { 
    console.log(this._hello); 
}; 

var f = new Foo(); 
f.bar(); // => "world!" 
f.bar.apply(this); // => undefined 

我知道apply變化的情況下,所以裏面barthis將是全局對象(在第二次調用)。

但我需要的是從Foo功能訪問this。我看到的解決方案是:

var Foo = function() { 
    var self = this; 
    self._hello = "world!"; 
    self.bar = function() { 
     console.log(self._hello); 
    }; 
}; 

但是,我會選擇不在另一個函數中有方法聲明。

我寧願定義方法(只是代碼風格)同列級:

var Foo = ...; 
Foo.prototype.method = ...; 

這可能嗎?怎麼樣?

+0

只是不打擾縮進你的代碼。 – 1983 2014-09-28 23:12:04

+0

這不是「範圍」,它是調用的*上下文* – Bergi 2014-09-29 20:59:41

+0

爲什麼要在'bar'上使用'apply'?你的電話怎麼看起來不是簡單的'f.bar()'? – Bergi 2014-09-29 21:00:50

回答

2

請參見您可以使用bind() method解決these kinds of problems。而不是something.method(f.bar)調用something.method(f.bar.bind(f))以獲取bar方法始終在預期的上下文中調用(f)。

如果你不想在你傳遞bar周圍作爲回調每個位置使用bind,你也可以把它在構造函數中默認創建的每個實例專用的約束功能:

function Foo() { 
    this._hello = "world!"; 
    this.bar = this.bar.bind(this); 
} 
Foo.prototype.bar = function() { 
    console.log(this._hello); 
}; 

var f = new Foo; 
something.method(f.bar); // works! 
+1

應該是'this._hello' – CupawnTae 2014-09-30 14:46:57

+0

這是正確的解決方案,但我不推薦它,因爲它不是我記憶友好。 – 2014-09-30 15:05:16

+0

@IonicăBizău:爲什麼?它不應該比關閉解決方案更少的內存友好。 – Bergi 2014-09-30 15:20:52

0

這樣做不可能通過將函數分配給原型來實現。

除非您直接指定f.bar(如第二個示例和Bergi的答案),否則f.bar將獲得的值是您分配給原型屬性Foo.prototype.bar的功能的參考。對於任何其他以Foo.prototype爲原型的對象,這將是完全相同的函數對象。此函數對象中沒有提及f

因此,當您撥打f.bar()時,this如何參考值f?這是一種特殊的語法,基本相當於f.bar.apply(f)。只有您使用此方法調用語法才能將this設置爲f的值。對f.bar的任何其他參考將僅評估原型的單個共享函數對象。

如果用f.bar.apply(somethingElse)調用它,則this現在設置爲somethingElse,並且與f的所有關聯都將丟失。

這不是apply(...)改變範圍的問題。 fn.apply(x)設置thisxfn內,而y.fn()設置thisy

同樣,在你的例子,如果你指定f.bar給一個變量,然後通過該變量調用它,而不是使用方法調用的語法f.bar()的,你this將是window對象(如果在瀏覽器中運行),並再次你會得到undefined

var func=f.bar; // now func === Foo.prototype.bar 
func(); // => undefined 

How to find the object a function belongs to?

相關問題