2012-10-04 70 views
1

我知道如何解決這個特定的問題,但我想知道它爲什麼會發生。基本上,當我嘗試調用的函數是這樣的:由三元運算符返回的函數丟失上下文

(callFoo ? this.foo : this.bar)(); 

它調用正確的富功能,但FOO內,this是全球性的,窗口對象,而不是我期待的對象。

我希望這做同樣的事情,但它並不:

(this.foo)(); 

上面的代碼調用正確的函數,並保持正確的上下文(this是什麼,我希望它是)。

Here is a jsfiddle for you to play around with.

可能有人請解釋一下到底是怎麼回事?我知道如何解決這個問題(我甚至不是那種語法的粉絲),但我仍然想知道爲什麼this成爲窗口,如果你從三元運算符返回一個函數。


編輯
我想改進我的問題: 這讓我感覺這個:

(callFoo ? this.foo : this.bar)(); 

等同於:

var f = (callFoo ? this.foo : this.bar); 
f(); 

它爲什麼this成爲該功能中的窗口。

爲什麼不同樣的事情發生在這裏:

(this.foo)(); 

回答

1

原因的差異:

var obj = new (function MyConstructor(){ 
    this.getConstructor = function(){ return this.constructor.name; } 
}); 

當操作數是由任何操作員操作上,結果非常像函數的返回值。傳遞的對象方法不再被視爲綁定到對象。

(function(){ return obj.getConstructor; })(); //'Window' 

但在沒有什麼比屬性訪問其他的括號內發生的情況下,括號會被忽略,而不是運營商自己處理。所以:

(obj.getConstructor)(); //'MyConstructor' 

實際上只是相當於:

obj.getConstructor(); 

但增加導致方法中的任一種有效的操作:

(false || obj.getConstructor)(); //'Window' 

而且obj.getConstructor被視爲方法,而不是通過'。'綁定到對象的方法。協會。

+0

正是我所期待的。謝謝。並感謝您更正'(+ obj.getConstructor)()'位。我試圖想到類似的東西,但我不能。 – lbstr

+1

是的,我不應該認爲這只是因爲它可以與匿名函數一起工作。奇怪的是,本地對象方法並不一定遵循相同的行爲,即使它們的行爲好像他們以其他方式使用「this」一樣。 –

2

有正確的上下文調用對象,調用它

this[ callFoo ? 'foo' : 'bar' ](); 

this值總是取決於如何你調用一個函數。你基本上調用該函數就像

fnc(); 

導致this始終是全球/窗口(非嚴格模式)。您需要調用方法/屬性this.fnc()。在這種情況下,默認情況下,this將引用調用對象。

+0

感謝您的回答 - 我喜歡與'fnc()'的比較,因爲它很清楚上下文將會丟失。正如我所說,我明白如何解決它,但我更好奇爲什麼'(callFoo?this.foo:this.bar)()'與(this.foo)()'不同。 '(this.foo)'只是沒有評估?使它與'this.foo'完全相同? – lbstr

0

當您使用三元運算符時,您正在兩個函數之間進行選擇。這將是類似於做類似如下:

var func = this.foo; 
foo(); // Inside this call, "this" will now refer to the global context 
     // -- "window" in a browser environment 

這(即「本」)是在JavaScript中大棘手的事情之一,很多人都寫了。

當你在「this.foo」周圍拋出parens時,問題也不會發生,這有些令人驚訝。但是,這不是你的問題:-)

1

這個表達式是邏輯上等同於這樣的事情:

var tempFun; 
if(callFoo) { 
    tempFun = this.foo; 
} else { 
    tempFun = this.bar; 
} 
tempFun(); 

這是失去this參考的典型範例。至於你說的,你知道解決方法/解決方案:

tempFun.call(this); 

或:

(callFoo ? this.foo : this.bar).call(this) 
+0

我喜歡你如何分解成實際的if-else。它絕對有助於清理事情。任何解釋爲什麼'(this.foo)()'不會發生同樣的事情? – lbstr