2012-03-02 32 views
4

在下面的JavaScript代碼:混亂了在JavaScript中的功能與性能參考

function foo() { 
    foo.val = foo.val || 'no val'; 
    return 'foo has ' + foo.val; 
}; 
function bar() { 
    bar.val = bar.val || 'no val'; 
    return 'bar has ' + bar.val; 
}; 
var a = foo; 
foo.val = '1'; 
bar.val = '2'; 
a.val = '3'; 
foo = bar; 
'foo says "' + foo() + '", bar says "' + bar() + '", a says "' + a() +'"'; 

我期望是:

富說:「酒吧已2」,顯示的是「棒有2" 個,一個說 「富有3個」

然而,從Firebug控制檯在Firefox 10.0.2上運行時,我得到:

富說:「酒吧已2」,顯示的是「酒吧有2個」,一個說「富已經2」

誰能向我解釋事件的是那張幕後的順序進行這是嗎?爲什麼a保留綁定到原始foo函數(我所期望的),但保留bar的值爲val

回答

4

這行代碼後:

var a = foo; 

a指向相同的功能foo點。在

foo = bar; 

重新分配foo指向任何bar指。這不會更新a的參考 - 它仍然指向foo最初也指向的功能。

現在,當您運行a()時,將執行原始函數。它抓取foo(現在指向bar的引用)並獲取其val屬性。 barval的對象是2,所以這是返回的內容。

用文字解釋有點難......圖表會更容易理解嗎?

+1

+1。這是令人困惑的解釋,但我認爲你做得比我做得更好。 – nnnnnn 2012-03-02 01:36:41

+0

不需要圖表,這是一個很好的解釋。我正在尋找一種方法來引用沒有'arguments.callee'的函數,因爲它在ES5嚴格模式下引發了一個TypeError。我想我必須小心,不要重新分配我的功能。 – beldaz 2012-03-02 01:42:43

4

foo()功能通過a()調用執行,它的代碼表示,拿到foo.val的價值,那就是,無論fooval財產是指在那一刻。所以,你的a()功能,有效看起來是這樣的:

function a() { 
    foo.val = foo.val || 'no val'; 
    return 'foo has ' + foo.val; 
}; 

foo在這一點上僅僅是bar參考。

+1

啊。我曾想過(希望)foo函數定義中對'foo.val'的調用會綁定到原始函數。謝謝你清理那個。 – beldaz 2012-03-02 01:35:51