一 调用栈
我们知道栈的特点是,先进后出的。那么函数的执行上下文栈又是怎么样的呢?
先看这段代码
var a = 2
function p2(b,c){
return b+c;
}
function p1(b,c){
var d = 10;
result = p2(b,c);
return a + result + d;//2+9+10
}
console.log(p1(3,6));//21
由于js代码是 运行时编译,先进行词法解析、语法解析 生成AST(抽象语法树)生产、代码生成- 生成机器码(运行在浏览器上)。而在词法解析阶段,就会生成执行上下文。所以 js 的作用域 又叫 词法作用域。也就是说,js作用链查找与函数在哪里执行没有关系,而与函数在哪里定义有关系。
分析上面代码调用栈执行过程。
-
浏览器编译这段js代码,在词法解析阶段,创建全局执行上下文
-
执行全局js代码
将 2赋值给a,这儿用到了 lfs查询,查询到a的内存地址,并将 2 存入 该地址中。
查询console.log 函数并执行该函数(由于console.log 的执行上下文没有什么意义,故省略)
查询p1函数并编译p1函数(词法解析阶段 生成 p1的执行上下文,并压入执行上下文栈中)
注: 第张图有两处错误。
。 result 由于没有 使用 var定义,在p1的作用域中查询不到,会被定义到window上,不应该在 p1 函数执行上下文的变量环境中。
。还有,这儿p1函数有形参传值,在编译p1函数的 词法解析阶段 也会进行 b 和 c 的声明,这儿在图2中也没有体现。
p2 执行完毕,返回 3+6 等于9的值,p2函数执行上下文出栈。
函数p1中 ,将9赋值给 result变量;返回 a+ resutl+d 值(这三个都执行 rls查询,将查询结果相加);p1函数执行完毕,p1函数执行上下文出栈。将p1函数返回值传入console.log 的形参,执行 console.log 函数。