深入學習js系列是自己階段性成長的見證,希望通過文章的形式更加嚴謹、客觀地梳理js的相關知識,也希望能夠幫助更多的前端開發的朋友解決問題,期待我們的共同進步。
如果覺得本系列不錯,歡迎點贊、評論、轉發,您的支援就是我堅持的最大動力。
在《深入學習js之——執行上下文棧》中說過,當JavaScript程式碼執行一段可執行程式碼(executable code)時,會建立對應的執行上下文(execution context)
對於每一個執行上下文,都有三個重要的屬性:
變數物件(Variable object VO) 作用域鏈(Scope chain) this
本文我們結合著這三個部分的內容,講講執行上下文的具體處理過程。
思考題
在《深入學習js之——詞法作用域和動態作用域》中,提出這樣一道思考題:
// 思考題一:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
// 思考題二:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
複製程式碼
兩段程式碼都會列印local scope
,但是還是有些許差異的,本文就詳細的解析執行上下文棧和執行上下文的具體變化過程。
具體分析
我們分析第一段程式碼:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
複製程式碼
執行過程如下:
1、執行全域性程式碼,建立全域性執行上下文,全域性上下文被壓入執行上下文棧
ECStack = [
globalContext
];
複製程式碼
2、全域性上下文初始化
globalContext = {
VO: [global],
Scope: [globalContext.VO],
this: globalContext.VO
}
複製程式碼
2、初始化的同時,checkscope 函式被建立,儲存作用域鏈到函式內部的屬性[[scope]]
checkscope.[[scope]] = [
globalContext.VO
];
複製程式碼
3、執行checkScope 函式,建立checkScope 函式執行上下文,checkScope 函式執行上下文被壓入執行上下文棧:
ECStack = [
checkscopeContext,
globalContext
];
複製程式碼
4、checkscope 函式執行上下文初始化:
1.複製函式 [[scope]] 屬性建立作用域鏈, 2.用 arguments 建立活動物件, 3.初始化活動物件,即加入形參、函式宣告、變數宣告, 4.將活動物件壓入 checkscope 作用域鏈頂端,
同時 f 函式被建立,儲存作用域鏈到 f 函式的內部屬性[[scope]]
checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope: undefined,
f: reference to function f(){}
},
Scope: [AO, globalContext.VO],
this: undefined
}
複製程式碼
5、執行f函式,建立 f 函式執行上下文,f 函式執行上下文被壓入執行上下文棧
ECStack = [
fContext,
checkscopeContext,
globalContext
]
複製程式碼
6、f 函式執行上下文初始化, 以下跟第 4 步相同:
1.複製函式
[[scope]]
屬性建立作用域鏈 2.用 arguments 建立活動物件 3.初始化活動物件,即加入形參、函式宣告、變數宣告 4.將活動物件壓入 f 作用域鏈頂端
fContext = {
AO: {
arguments: {
length: 0
}
},
Scope: [AO, checkscopeContext.AO, globalContext.VO],
this: undefined
}
複製程式碼
7、f 函式執行,沿著作用域鏈查詢 scope 值,返回 scope 值
8、f 函式執行完畢,f 函式上下文從執行上下文棧中彈出
ECStack = [
checkscopeContext,
globalContext
]
複製程式碼
9、checkscope 函式執行完畢,checkscope 執行上下文從執行上下文棧中彈出
ECStack = [
globalContext
]
複製程式碼
深入學習JavaScript系列目錄
- #1 【深入學習js之——原型和原型鏈】
- #2 【深入學習js之——詞法作用域和動態作用域】
- #3 【深入學習js之——執行山下文棧】
- #4 【深入學習js之——變數物件】
- #5 【深入學習js之——作用域鏈】
- #6 【深入學習js之——實際開發場景中的this指向】
- #7 【深入學習js之——執行上下文】
- #8 【深入學習js之——閉包】
- #9 【深入學習js之——引數按值傳遞】
- #10 【深入學習js之——call和apply】
歡迎新增我的個人微信討論技術和個體成長。
歡迎關注我的個人微信公眾號——指尖的宇宙,更多優質思考乾貨