javascript作用域鏈理解

看風景就發表於2017-05-07
執行上下文(Execution context,簡稱EC)
 
概念
 
每當控制器到達ECMAScript可執行程式碼的時候,就進入了一個執行上下文。
 
javascript中,EC分為三種:
 
全域性級別的程式碼(全域性執行上下文)
函式級別的程式碼(函式執行性上下文)
Eval的程式碼(eval執行上下文)
 
執行上下文物件包括三個關鍵屬性,可能有其他自定義屬性。
 
VO(Variable object), 變數物件 或者 AO(activation object),活動物件,是個字典,包括函式arguments物件,形參,內部變數,函式宣告
 
Scope chain,作用域鏈物件,包括當前作用域的vo和所有父級作用域的vo。
 
this物件,Context object,上下文物件。
 
 
作用域鏈的鏈式結構
 
作用域鏈的鏈式結構,是AO有個父級變數物件的引用,用
__parent__內部屬性指代。則通過對父級的應用形成一種
鏈式結構,如下圖
 
作用域鏈結構圖片
 
執行上下文的執行過程
 
EC的建立分為兩個階段:進入執行上下文階段和程式碼執行階段
 
1.進入上下文階段
 
發生在函式呼叫時,在執行具體程式碼之前。做如下三件事:
建立作用域鏈(Scope Chain)
建立變數物件
設定this物件的值,this物件的值取決於物件的呼叫者,caller和呼叫方式決定了this的值。
 
變數物件中的變數值如下:
根據函式引數建立並初始化arguments物件
函式宣告建立屬性,關聯具體函式
變數初始化為undefined(所謂變數提升)
 
同名覆蓋原則
函式宣告與引數同名 函式宣告覆蓋引數
變數與函式宣告或引數同名,變數賦值前其有效
 
2.程式碼執行階段
 
變數賦值
解釋執行其他程式碼
 
執行上下文的建立會形成一個棧,新建立的執行上下文入棧,執行完畢則出棧。
 
程式執行時,首先進入全域性執行上下文,Global Context入棧,
在全域性中有函式呼叫,則會進入函式執行上下文,函式執行上下文入棧
 
執行上下文棧 圖片
 
閉包

定義

包含自由變數的函式就是閉包(自由變數指不是函式引數,也不是函式內部變數的變數,即外部變數)
該函式通常為內部函式,被返回,外部可以引用該函式,通過其訪問自由變數。

閉包的用途

1. 讀取函式內部的變數
2. 讓變數的值始終保持在記憶體中,比如迴圈註冊事件,在事件中訪問迴圈變數,需要用閉包來保持迴圈變數
3. IIFE(立即呼叫的函式表示式),在引用了外部變數的時候,也會形成閉包,形成一個獨立的作用域,防止變數汙染

閉包注意點

1. 閉包會使得父級作用域的變數都被儲存在記憶體中,記憶體消耗大,在IE中可能會導致記憶體洩漏。少用閉包,或者將不使用的區域性變數全部刪除
2. 父級作用域的變數是共享,一個閉包修改了變數的值,其他閉包的值獲取的值也會發生變化,容易產生錯誤

相關文章