作用域:全局、函数、eval。可参考《函数与作用域01》和《函数与作用域02》。
1、概念
执行上下文类似于栈的结构,可参考《深入理解Javascript之执行上下文》
1 | console.log("EC0"); |
解析: 变量对象(VO)是一个抽象概念的“对象”,它用于存储执行上下文中的变量、函数声明、函数参数
可以将上下文看成一个对象
1 | activeExecutionContext = { |
2、全局执行上下文(浏览器)
1 | VO(globalContext) === [[global]]; |
3、函数激活对象(AO)
1 | // 函数初始化 |
3.1 变量初始化阶段
1 | function test(a, b) { |
VO按照如下顺序填充:
函数参数(若未传入,初始化该参数值为undefined)
函数声明(若发生命名冲突,会覆盖)
变量声明(初始化变量值为undefined,若发生命名冲突,忽略)
1 | function foo(x, y, z) { |
解析: 函数参数传进去之后,因为函数声明跟参数命名发生冲突,即x直接覆盖函数参数变量
1 | function foo(x, y, z) { |
解析: 变量声明跟函数声明的命名发生冲突,根据VO的顺序,变量声明发生冲突,则会被忽略
1 | function foo(x, y, z) { |
解析: 初始化阶段变量声明因为命名冲突会被忽略,但是在第二个阶段,即执行阶段func = 1
会被赋值为1,则就是为什么结果1的原因了。
注意: 函数表达式不会影响VO。上文的var e = function _e(){}
中的_e匿名函数,e的变量声明会被放在右边的AO里面,执行阶段的时候才有把匿名函数_e赋值给变量e。这就是为什么我们没办法通过_e来访问函数对象。
3.2 代码执行阶段
该阶段会对上一阶段初始化的变量进行赋值
1 | AO(test) = { |
栗子:
1 | console.log(x); // function x() {} |
解析:
初始化阶段
函数参数:上下文测试不存在函数参数问题
函数声明:
function x() {}
变量声明:
var x
命名冲突,忽略;var a; var b
undefined
执行阶段
1 | console.log(x); // function x() {} |