javascript作用域鏈理解
阿新 • • 發佈:2017-05-07
sco 執行上下文 變量提升 返回 結構圖 活動 ren 產生 內部 執行上下文(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. 父級作用域的變量是共享,一個閉包修改了變量的值,其他閉包的值獲取的值也會發生變化,容易產生錯誤
javascript作用域鏈理解