原文出處
具體執(zhí)行分析
代碼如下:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
執(zhí)行過(guò)程如下:
- 執(zhí)行全局代碼,創(chuàng)建全局執(zhí)行上下文肛真,全局上下文被壓入執(zhí)行上下文棧
ECStack = [
globalContext
];
- 全局上下文初始化
globalContext = {
VO: [global],
Scope: [globalContext.VO],
this: globalContext.VO
}
- 初始化的同時(shí)本讥,checkscope 函數(shù)被創(chuàng)建典唇,保存作用域鏈到函數(shù)的內(nèi)部屬性[[scope]]
checkscope.[[scope]] = [
globalContext.VO
];
- 執(zhí)行 checkscope 函數(shù)侯勉,創(chuàng)建 checkscope 函數(shù)執(zhí)行上下文捶闸,checkscope 函數(shù)執(zhí)行上下文被壓入執(zhí)行上下文棧
ECStack = [
checkscopeContext,
globalContext
];
- checkscope 函數(shù)執(zhí)行上下文初始化:
- 復(fù)制函數(shù) [[scope]] 屬性創(chuàng)建作用域鏈夜畴,
- 用 arguments 創(chuàng)建活動(dòng)對(duì)象拖刃,
- 初始化活動(dòng)對(duì)象,即加入形參贪绘、函數(shù)聲明序调、變量聲明,
- 將活動(dòng)對(duì)象壓入 checkscope 作用域鏈頂端兔簇。
同時(shí) f 函數(shù)被創(chuàng)建发绢,保存作用域鏈到 f 函數(shù)的內(nèi)部屬性[[scope]]
checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope: undefined,
f: reference to function f(){}
},
Scope: [AO, globalContext.VO],
this: undefined
}
- 執(zhí)行 f 函數(shù),創(chuàng)建 f 函數(shù)執(zhí)行上下文垄琐,f 函數(shù)執(zhí)行上下文被壓入執(zhí)行上下文棧
ECStack = [
fContext,
checkscopeContext,
globalContext
];
-
f 函數(shù)執(zhí)行上下文初始化, 以下跟第 4 步相同:
- 復(fù)制函數(shù) [[scope]] 屬性創(chuàng)建作用域鏈
- 用 arguments 創(chuàng)建活動(dòng)對(duì)象
- 初始化活動(dòng)對(duì)象边酒,即加入形參、函數(shù)聲明狸窘、變量聲明
- 將活動(dòng)對(duì)象壓入 f 作用域鏈頂端
fContext = {
AO: {
arguments: {
length: 0
}
},
Scope: [AO, checkscopeContext.AO, globalContext.VO],
this: undefined
}
- f 函數(shù)執(zhí)行墩朦,沿著作用域鏈查找 scope 值,返回 scope 值
- f 函數(shù)執(zhí)行完畢翻擒,f 函數(shù)上下文從執(zhí)行上下文棧中彈出
ECStack = [
checkscopeContext,
globalContext
];
- checkscope 函數(shù)執(zhí)行完畢氓涣,checkscope 執(zhí)行上下文從執(zhí)行上下文棧中彈出
ECStack = [
globalContext
];