下面以一个简单例子进行分析,主要讲解是第二部分执行阶段。
var a = 2; function bar() { var b = 2; function foo() { var c = 2; } foo(); } bar();用伪代码模拟全局对象的大体结构如下:
//创建一个全局对象 var globalObject = { Math:{}, String:{}, Date:{}, document:{}, //DOM操作 ... window:this //让window属性指向了自身 }这个栈用于存储数据
每次当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。
JS的执行作用域有三种:
全局环境:JavaScript代码运行起来会首先进入该环境函数环境:当函数被调用执行时,会进入当前函数中执行代码eval、with(不建议使用,可忽略)当浏览器首次载入你的脚本,它将创建全局执行上下文。
在全局代码中调用一个函数,就会创建一个执行上下文。
JS的引擎会以栈的方式来处理这些执行上下文。栈底永远都是全局上下文,而栈顶就是当前正在执行的上下文。
而处于栈顶的上下文执行完毕之后,就会自动出栈。
如下图所示:
执行上下文的生命周期包括三个阶段:创建阶段->执行阶段->回收阶段
当函数被调用,但未执行任何其内部代码之前, 会做以下三件事:
函数声明的优先级要高于var声明。
作用域链是在变量对象之后创建的
作用域链是由当前作用域与上层一系列父级作用域组成
当被要求解析变量时,JavaScript始终从代码嵌套的最内层开始, 如果最内层没有找到变量, 就会跳转到上一层父作用域中查找,直到找到该变量。
this是在执行上下文创建阶段确定的,即在函数执行的时候确定的
执行阶段JS引擎会进行变量赋值、函数引用、执行其他代码,执行顺序取决于代码的位置
在执行阶段变量对象(Variable Object)变为活动对象(Active Object)。 VO => AO
变量对象和活动对象其实是同一个对象,只是处于执行上下文的不同生命周期不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。
执行上下文出栈等待虚拟机回收执行上下文
