在之前写的进阶系列里面,提到了
执行上下文
在创建阶段,要创建变量对象
、确定作用域链
还有确定this的指向
,本次将重点讲解一下作用域链
。
JavaScript代码的执行过程
在讲解作用域链之前,首先了解一下,JavaScript代码的执行过程,包括两个步骤:
- 编译阶段
- JavaScript引擎执行阶段
在编译阶段主要做的是,经过编译器的编译,将代码转化为可执行的代码,其中就包括了作用域规则的确定
,而在之前说的执行上下文的创建和执行阶段是发生在JavaScript隐引擎执行阶段,所以作用域链
是在执行上下文创建阶段才产生的,这时候,可能你会疑惑,作用域和作用域链有什么区别呢?
什么是作用域?
作用域为一套规则,用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符查找变量。
在JavaScript中,主要的作用域有两种:
- 全局作用域
- 函数作用域
什么是作用域链?
作用域链是由当前执行环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
而作用域与作用域链的区别主要在于:
作用域是一套规则,作用域链是作用域的具体实现。
讲理论可能有些空洞,那么我就举个具体的例子来说明什么是作用域链吧
demo01
var a = 20;
function test(){
var b = a + 20;
function innerTest(){
var c = 10;
return b + c;
}
return innerTest();
}
test();
在这个例子中,按照之前讲解的
- 先创建执行上下文,按照,
globalEC
—>testEC
—>innerTestEC
的顺序,压入调用栈
中,其中主要讨论innerTest()
的作用域链。 - 按照作用链的定义,可以得出
innerTest()
执行上下的结构,如下
innerTestEC = {
VO:{ c:10},
scopeChain:[VO(innerTest),VO(test),VO(global)],
this:{...}
}
可以看出,innerTest()
的作用域链就是由当前的执行环境与上层的执行环境中的一系列变量对象组成,所以innerTest()
就能访问到上层执行上下文中,变量对象中的属性和方法,这就是作用域链。
- 看一下
innerTest()
的作用域链图,如下: