2015-11-25 64 views
0

以下是我想要啓發的示例(某些實際上不起作用的示例)。Javascript中的作用域鏈,並在全局範圍內調用嵌套函數

var myVar = 2; 

    function a(){ 
    var myVar = 2; 
     function b(){ 
      console.log(myVar); 
     } 
    }; 
    a(); 
    b(); 

這將在控制檯輸出:Uncaught ReferenceError:b未定義。

正如你所看到的,我有一個函數名爲a與嵌套函數b

起初,我以爲我可以調用b一個並讓它正常工作。 我認爲這將起作用,因爲一開始我稱之爲函數。

通過這樣做,我心目中的事實功能將在執行堆棧,並在其創作階段中定義的B功能放在將在存儲器中設置。

由於這是在內存中,我認爲我可以在函數外執行此操作。這顯然不起作用。

所以我的結論是B功能的創建階段的功能確實設置到內存,但一旦功能已完成執行,一旦它的彈出執行堆棧中,b函數同時彈出內存。

因此,在全球範圍內調用它(我的意思是b函數)是不可能的。

我對嗎?

+0

JavaScript具有[*詞法範圍*](https://en.wikipedia.org/wiki/Scope_%28computer_science%29#Lexical_scoping)並且也適用於函數。 –

回答

3

通過談論執行堆棧,創建階段等,您將不必要地複雜化。

解釋非常簡單:您不能撥打b,因爲規範說b超出了您嘗試對其進行調用的網站的範圍。這就是結局。

如果轉換爲PHP,您的示例實際上可以工作,這讓我覺得這也許是您從中獲得靈感的地方。但JS和PHP是不同的語言和PHP處理嵌套函數的(IMO荒謬)方式不會轉移。

+0

是的,你是對的,我試圖在反思中做得太深......我知道我不能用Javascript做到這一點,但我試圖完全理解爲什麼。所有的機制都參與其中。但實際上它更簡單。解釋是名爲'b'的函數位於名爲'a'的函數內。然後,當我們嘗試從全局範圍調用它時,它會失敗,因爲全局執行環境將查找函數b,但在全局執行上下文的創建階段,它從未添加到其變量環境中......總之,他們和你告訴我的範圍不一樣。謝謝 – Azuk

0

如果你想打電話b以外的a,你需要的a之外創建對它的引用:

var myVar = 2; 

function a(){ 
    var myVar = 2; 
    function b(){ 
     console.log(myVar); 
    } 
    return b; 
}; 

var b = a(); 
b(); 

不過,這不會造成b打印全球myVar。它仍然可以訪問a關閉範圍內的myVar