注意文中所指做用域和執行上下文都有全局和局部之分,爲方便理解採用局部。
本文參考引自: 思否:執行上下文和做用域的理解
做用域:
js中的做用域是詞法做用域,即由函數聲明時所在的位置決定的。segmentfault
執行上下文:
每次函數調用時,都會產生一個新的執行上下文環境。函數
做用域:
js中的做用域是詞法做用域,是在編譯階段就產生的,一整套函數標識符的訪問規則。做用域只是一個「空地盤」,其中並無真實的變量,可是卻定義了變量如何訪問的規則。this
做用域鏈本質上是一個指向變量對象的指針列表,它只引用不包含實際變量對象。定義了當變量訪問不到的時候如何向上查詢的一套規則。spa
執行上下文:
每次函數執行都會產生執行上下文,JavaScript引擎會以棧的方式來處理它們,這個棧,咱們稱其爲函數調用棧(call stack)。棧底永遠都是全局上下文,而棧頂就是當前處於活動狀態的正在執行的上下文,也稱爲活動對象(running execution context,圖中藍色的塊),區別與底下被掛起的上下文(變量對象)。指針
let fn, bar; // 一、進入全局上下文環境 bar = function(x) { let b = 5; fn(x + b); // 三、進入fn函數上下文環境 }; fn = function(y) { let c = 5; console.log(y + c); //四、fn出棧,bar出棧 }; bar(10); // 二、進入bar函數上下文環境
創建執行上下文階段(發生在 函數被調用時 && 函數體內的代碼執行前 )code
PS:我的以爲這個階段也能夠叫編譯階段:首先js是解釋型語言,解釋一條執行一條。其次函數內部的代碼在執行前並無作特殊處理,好比函數體內有語法錯誤,只有調用了函數纔會報錯,而在初始化js解析的時候並無發生任何報錯信息。
一、 生成變量對象:建立 arguments 對象 --> 建立function函數聲明 --> 建立var變量聲明;
二、 生成做用域鏈
三、 肯定this的指向對象
函數執行階段blog
變量賦值,函數引用,執行其它代碼ip
由定義可知,做用域是在函數聲明的時候就肯定的一套變量訪問規則,而執行上下文是函數執行時才產生的一系列變量的集合體。也就是說做用域定義了執行上下文中的變量的訪問規則,執行上下文是在這個做用域規則的前提下執行代碼的。作用域