文章目录
  1. 1. 作用域链
    1. 1.1. 1.创建/声明
    2. 1.2. 2.执行阶段
      1. 1.2.1. 2.1创建阶段
      2. 1.2.2. 什么是变量对象
      3. 1.2.3. 变量对象的创建过程
      4. 1.2.4. 2.2激活/执行阶段

作用域链

1.创建/声明

作用域链是与执行环境相关的。在JavaScript中,“一切皆对象”,而函数的这个对象有一个内部属性[[scope]],该内部属性指向了该函数的作用域链,而作用域链中存储了每个执行环境相关的变量对象。

每当声明或者创建一个函数的时候,那么会创建这个函数的作用域链,但是注意.此时这个作用域链只包含一个变量对象(window/global object全局对象).

2.执行阶段

当函数被调用的时候,就会创建一个新的执行环境.然而解释器的内部,每次调用执行环境会有两个阶段:

2.1创建阶段

当函数被调用,但是未执行内部代码之前:

1.创建变量对象(VO),由变量、函数声明、和参数组成.
2.确定this指向.
3.初始化(建立)作用域链(scope chain),相对这个新的执行环境.

什么是变量对象

变量对象是与执行上下文对应的概念,定义着执行上下文下的所有变量、函数以及当前执行上下文函数的参数列表。也就是说变量对象定义着一个函数内定义的参数列表、内部变量和内部函数。

数据结构上来说,它是这样的:

变量对象的创建过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function outerFun (arg1, arg2) {
var outerV1 = 1
var outerV2 = 2
function innerFun1 () {
var innerV1 = 3;
var innerV2 = 4;
console.log('i am innerFun1...')
}
function innerFun2 () {
console.log('i am innerFun2...')
}
function outerV2 () {
return 'i am outerV2'
}
}
outerFun()

它的变量对象创建过程是这样的:

这个创建变量对象的过程实际就是函数内数据(函数参数、内部变量、内部函数)初始化的过程。

2.2激活/执行阶段

赋值,引用函数,解释/执行代码。

进入执行阶段之后,变量对象转变(VO)为了活动对象(AO),里面的属性都能被访问了,然后开始进行执行阶段的操作。所以活动对象实际就是变量对象在真正执行时的另一种形式。

这个对象(活动)就会被存储在该函数的[[scope]]属性所指向的作用域链中,而之前的对象就被压在了新的变量对象的下边,这个可以类比栈,新的变量对象就放在了栈的最顶端,给最顶端的序号为0,向下以此类推,有点像倒金字塔模型

1
2
3
4
5
6
7
var a = 8;
function sum(num1, num2){
var sum = num1 + num2;
console.log(a);
return sum;
}
var sum = sum(3, 4);

当以后我们需要查找变量的时候,就总是会沿着这个作用域链的顶端(序号0/栈顶)开始查找,一直到作用域链(栈底)的末端,直到找到为止。也就是说顶端的活动对象可以访问到其后面的参数.

文章目录
  1. 1. 作用域链
    1. 1.1. 1.创建/声明
    2. 1.2. 2.执行阶段
      1. 1.2.1. 2.1创建阶段
      2. 1.2.2. 什么是变量对象
      3. 1.2.3. 变量对象的创建过程
      4. 1.2.4. 2.2激活/执行阶段