2012-10-31 43 views
1

在JavaScript中,你可以在一堆不同的方式定義功能:爲什麼局部變量名稱優先於JavaScript中的函數名稱?

function BatmanController() { 
} 

var BatmanController = function() { 
} 

// If you want to be EVIL 
eval("function BatmanController() {}"); 

// If you are fancy 
(function() { 
    function BatmanController() { 
    } 
}()); 

偶然我今天跨越意外的行爲跑去。當聲明一個局部變量(用奇特的方式)和函數名相同時,局部變量在局部範圍內出現。例如:

(function() { 
    "use strict"; 

    function BatmanController() { 
    } 

    console.log(typeof BatmanController); // outputs "function" 

    var RobinController = function() { 
    } 

    console.log(typeof RobinController); // outputs "function" 

    var JokerController = 1; 
    function JokerController() { 

    } 
    console.log(typeof JokerController); // outputs "number", Ehm what? 
}()); 

誰知道爲什麼var JokerController不受function JokerController覆蓋?我在Chrome,Safari,Canary,Firefox中測試了這一點。我想這是由於在V8和JägerMonkey引擎中進行了一些「向前看」的JavaScript優化。但是有沒有解釋這種行爲的技術解釋?

回答

4

由於功能和可變聲明被提升到在它們發生的範圍的頂部,但分配到位發生。你的代碼是有效地解釋爲這樣:

(function() { 
    "use strict"; 

    function BatmanController() {} // Declarations are hoisted 
    function JokerController() {} 

    var RobinController, // Declarations are hoisted 
     JokerController; 

    RobinController = function() {} // Assign function to RobinController 

    // outputs "function" (declaration was hoisted to top of scope) 
    console.log(typeof BatmanController); 

    // outputs "function" (assignment of number hasn't happened yet) 
    console.log(typeof RobinController); 

    JokerController = 1; // Assign number to JokerController 

    // outputs "number" (assignment of number has now happened) 
    console.log(typeof JokerController); 
}()); 

對於全部的技術細節,我建議你讀section 10.5 of the spec

+0

謝謝,這就是爲什麼我愛得如此。 – fredrik

1

您聲明JokerController函數的方式會導致函數定義被提升到範圍的頂部。換句話說,實際上是運行的代碼看起來是這樣的:

function JokerController(){} 
var JokerController = 1; 

如果聲明一個函數作爲匿名功能對象,參考/分配給一個變量,則該函數定義爲表達式的一部分,因此不能在當前範圍的頂部懸掛。

See paragraph titled Function on MDN

相關問題