2014-04-26 23 views
0

我正在關注article on javascript closures嵌套執行上下文的生存期

在試圖瞭解執行環境的細節時,我遇到了令我感到驚訝的結果。

var globalVar = 'g'; 
var inner; 
var outer = function() { 
    var outerVar = 'o'; 
    inner = function() { 
    var innerVar = 'i'; 
    console.log(innerVar, outerVar, globalVar); 
    } 
} 

outer() 
inner() // Q: What does this log out? 

http://jsfiddle.net/6zvsh/

這實際上輸出i o g

我期待看到i undefined g

這是我對過程的理解。我想了解我的錯誤:

  1. inner被聲明爲全局對象的屬性和值設置爲undefined
  2. outer被調用。
  3. outer創建執行上下文,其作用域鏈包括outerVar和全局對象。
  4. 全局對象上inner屬性的值被賦予對函數定義的引用。
  5. 完成outer的執行上下文。 (相關示波器被刪除?標記爲GC?)
  6. inner被調用。
  7. 創建一個執行上下文,其作用域鏈包括innerVar和全局對象。
  8. outerVar的範圍並不

發現有人可以解釋爲什麼outerVar定義?

+1

你剛發現關閉! [JavaScript關閉如何工作?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Bergi

+0

這也可能是答案:http://stackoverflow.com/a/ 11148475/111243 – SimplGy

+0

@Bergi,這個評論可能會超出必要的範圍。我認爲這是一個關於調用和聲明之間的細微差別的問題,我不明白,而不是需要一個總體的概述。我正在閱讀幾個不同的概述,只是一樣:) – SimplGy

回答

1

創建函數時,它將其周圍的執行上下文作爲範圍引用,從而爲其創建一個closure

讓我們一步步通過它:

1. inner is declared as a property on the global object and the value is set to undefined

1.5。該outer功能被創建,引用全球範圍內作爲其父範圍

2. outer is invoked.

3. An execution context is created for outer whose scope chain includes outerVar and the global object.

...因爲新的執行上下文的鏈鏈接引用的outer父範圍,該範圍(1.5分配)在全球範圍內。 outerVar是這個新的執行上下文中的一個變量。

4. The value of the inner property on the global object is assigned a reference to the function definition.

...並且函數的父範圍設置爲outer的執行上下文。

5. The execution context for outer finishes. (the related scopes are removed? marked for GC?)

...但不是垃圾收集,因爲它仍然作爲inner功能,還活着(不垃圾)的母公司範圍引用。

6. inner is invoked.

7. An execution context is created whose scope chain includes innerVar and the global object.

新執行上下文具有範圍鏈連結inner父上下文,它是上述用於outer呼叫(具有鏈鏈接到全球範圍內)創建的執行上下文。 innerVar是這個新執行上下文中的一個變量。

8. outerVar is not found in scope

...鏈。

+1

太棒了。我認爲我錯過的關鍵是將範圍分配給函數對象的時機。我總結如下:問:爲什麼它可以訪問'outerVar'?答:因爲當'outer'運行時,會爲'inner'創建一個函數對象,其[[scope]]被賦予outer的執行上下文的值。外部的執行上下文的範圍是一個包含激活/變量對象(參數,outerVar)和全局對象的鏈。因爲GC可以看到從全局'inner'屬性到外部的executionContext範圍的引用,所以該範圍得以維護。 – SimplGy

+0

是的,確切地說。只有我沒有專注於使用正確的術語(沒有時間引用[相關規範部分](http://es5.github.io/#x10.3)),請原諒我是否混合了術語「範圍」和「執行上下文」。 – Bergi