(1) js引擎执行代码时候/前,在堆内存创建一个全局对象,该对象 所有的作用域(scope)都可以访问,里面会包含Date、Array、String、Number、setTimeout、setInterval等等,其中还有一个window属性指向自己
(2) js引擎执行代码时候会创建执行上下文栈,最开始执行全局代码,创建全局执行上下文
(3) 全局执行上下文 放到 执行上下文栈 ,这里面里面包括两部分内容:3.1把全局定义的变量,函数加到全局对象里面,但不会赋值,这一过程也就是变量作用域提升。3.2在执行代码中,对变量赋值,或者执行其他的函数
(4) 每一个执行上下文会关联一个vo(Variable Object)变量对象
(5) 全局代码被执行时候,这个vo对象就是全局对象了
(6) 执行过程中全局代码中遇到了函数,创建函数执行上下文(这里也就是执行上下文有哪几种了,全局,函数,eval函数这个一般不用也不建议用),接着把函数执行上下文放进执行上下文栈,上面说了每个执行上下文要有关联一个vo变量对象,当进入一个函数执行上下文时候,会创建一个AO对象(activation object),这个AO会作为函数的VO,会使用argument来初始化,并且初始化的值是传入的参数,如果函数里面还有函数,那继续创建函数执行上下文,也就是压栈,执行完毕出栈。以此执行
(7) 我们了解了变量对象后,代码在其上下文的执行环境的执行的过程中,会创建变量对象的一个作用域链,这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。
函数的作用域在函数创建时就已经确定了。当函数创建时,会有一个名为 [[scope]] 的内部属性保存所有父变量对象到其中。当函数执行时,会创建一个执行环境,然后通过复制函数的 [[scope]] 属性中的对象构建起执行环境的作用域链,然后变量对象 VO 被激活生成 AO 并添加到作用域链的前端,完整作用域链创建完成
简单来说:沿着作用域链,内层代码可以访问外层声明变量与函数,外层无法访问内层声明的变量与函数