之前对于执行上下文和作用域链总是模模糊糊的,经过几天的学习后,大概有所了解了,就把我这几天学习的总结一下,和大家一起看看。如有错误还望大佬指正!!
var globalScope = "global scope";
function checkScope() {
var localScope = "local scope";
function innerFunction() {
return localScope;
}
return innerFunction();
}
console.log(checkScope());
这个会打印什么呢,就根据js的运行机制,一起走一遍把
- 开始执行:最初,执行栈中只有全局执行上下文
ECStack = [globalContext]。这个时候会有一个变量对象的概念VO,全局的变量就保存在globalContext.VO里,可以理解为globalContext.VO = {globalScope: "global scope"}
//当前的执行栈就是
ECStack = [globalContext]
- 函数定义阶段:当定义
checkScope函数时,会保存父级的变量对象到函数的内部属性[[scope]]里,即checkscope.[[scope]] = globalContext.VO - 函数执行:当
checkScope函数执行时,会创建一个checkScopeContext的执行上下文
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
4.函数执行前准备:.checkscope函数执行前会做一些准备工作,就是复制函数的[[scope]]属性然后创建作用域,还记得这个属性保存的是什么吗,保存的就是父级的变量对象
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
//当前函数的作用域链,Scope属性代表当前函数的作用域链
checkScopeContext={Scope: [ checkScope.[[scope]] ]}
5.函数创建活动对象:接下来checkscope函数会创建活动对象AO,可以理解为和VO意思一样
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
//当前函数的作用域链,Scope属性代表当前函数的作用域链
checkScopeContext={
AO: {
arguments: {
length: 0
},
localScope: undefined,
innerFunction: reference to function innerFunction(){},
},
Scope: [ checkScope.[[scope]] ]
}
- 函数给活动对象赋值:接下来checkscope函数会给AO赋值,并把AO压入作用域链Scope里
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
//当前函数的作用域链,Scope属性代表当前函数的作用域链
checkScopeContext={
AO: {
arguments: {
length: 0
},
localScope: "local scope",
innerFunction: reference to function innerFunction(){},
},
Scope: [ AO,checkScope.[[scope]] ]
}
- 函数准备工作完成开始执行:首先遇到innerFunction函数定义,遇到定义保存父级的变量对象到[[scope]]里,即innerFunction.[[scope]] = checkScopeContext.AO
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
- 重复上一个函数的执行过程:先复制[[scope]]到作用域链,在创建AO,赋值AO,压入AO到作用链里
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext,innerFunctionContext]
//当前函数的作用域链,scope属性代表当前函数的作用域链
innerFunctionContext = {
AO: {
arguments: {
length: 0
},
},
Scope: [ AO,innerFunction.[[scope]] ]
}
- 执行innerFunction函数:return
localScope在innerFunctionContext.Scope作用域链开始查找,先查看AO,发现并没有localScope,再查找innerFunction.[[scope]],这个值就是checkScopeContext.AO,可以发现checkScopeContext.AO里有localScope = local scope,所以就返回local scope
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext,innerFunctionContext]
//当前函数的作用域链,scope属性代表当前函数的作用域链
innerFunctionContext = {
AO: {
arguments: {
length: 0
},
},
Scope: [ AO,innerFunction.[[scope]] ]
}
10.执行innerFunction函数完成:弹出innerFunction执行上下文
//当前的执行栈就是
ECStack = [globalContext,checkScopeContext]
11.执行checkScopeContext函数完成:弹出checkScopeContext执行上下文
//当前的执行栈就是
ECStack = [globalContext]
- 代码执行完毕 打印出local scope
var globalScope = "global scope";
function checkScope() {
var localScope = "local scope";
function innerFunction() {
return localScope;
} return innerFunction;
}
console.log(checkScope()());
这种情况会打印什么呢,大家说吧!