2017-05-03 57 views
0

我閱讀了很多關於javascript作用域鏈的文章,並且我認爲我對它有相當的理解。然而,一個非常簡單的練習讓我意識到我還沒有理解它。Javascript - 作用域鏈

我創建了以下代碼。

function foo() { 
    var b = 2; 

    bar() 

} 

function bar() { 
    console.log(b); 

} 

foo(); 

此代碼給出了參考錯誤。但是,我認爲它仍然會打印出2.我的推理如下:

  • 函數聲明foo和bar。
  • Foo被執行,這會創建一個新的執行上下文。 Foo具有內部屬性[[Scope]設置爲全局。
  • var b已懸掛。
  • var b被賦值爲2.
  • bar在foo執行上下文中執行。因此,我認爲bar函數的內部屬性[[Scope]]將被設置爲foo。
  • b沒有在功能欄中定義,因此scopechain被查找並找到值b = 2.
  • console.log(2);

我的推理是基於我明白函數X的[[Scope]]內部屬性被設置爲在執行函數X時運行的執行上下文。不基於聲明函數X的地方。

回答

3

b定義爲foo的範圍。

barfoo的範圍調用,是的,但它的定義在foo的範圍之外。這意味着bar無法訪問b

作爲圖像往往可以幫助:

enter image description here

考慮每個紅色方塊是一個 「範圍」。 foobar共享外部範圍,但它們不能訪問彼此的內部範圍。

+0

切爾布魯斯感謝您的快速響應。讓我困惑的部分是在stackoverflow上提出的這個問題。 http://stackoverflow.com/questions/21128496/javascript-when-does-the-scope-chain-created。就你所描述的方式而言,在我看來,範圍鏈由聲明函數的執行上下文(即其詞法環境)決定,而不是由函數在哪個執行上下文中調用。然而,這個相關問題的答案似乎暗示了後者? –

+0

@JackSpar:我不確定那個答案的最後一行是什麼意思。很難說沒有一個例子。我確信的一件事是'b'不可訪問,因爲它在'foo'的範圍內。 – Cerbrus

+0

好,那我想我理解你。只是爲了確認我的理解。下面的代碼不會被認爲是閉包(程序員通常會這麼說),因爲函數baz應該已經可以訪問函數foo的作用域了,因爲它在那裏定義/聲明瞭? http://jsbin.com/nixitocuhi/edit?js,console –

1

讓我以不同的方式編寫代碼來解釋範圍。

var scope = {}; 
scope.foo = function() { 
    var b = 2; 
    scope.bar() 
} 

scope.bar = function() { 
// this will look for a property 'b' defined in the bar method, but it doesn's exist 
    console.log(b); 
// changing the console.log call to match the changes made above, means it will 
// look like this 
    console.log(scope.b) 
// but now scope.b is also not defined 
} 

scope.foo(); 

換句話說,當您嘗試訪問「B」裏面「酒吧」,它將搜索它在「酒吧」創建範圍,而不是在「酒吧」被稱作範圍。

+0

這真的有助於可視化範圍:-) – Cerbrus

+0

謝謝你的幫助! –