当JavaScript代码执行一段可执行的代码时,会创建对应的执行上下文,对于每个执行上下文的创建阶段,都有三个重要动作:
- 生成变量对象
- 建立作用域链
- 确定this的指向
变量对象
不同的执行上下文下的变量对象稍有不同,所以我们从全局上下文的变量对象和函数上下文的变量对象
全局上下文
先来了解一下全局对象:
全局对象是预定义的对象,作为JavaScript的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他预定义的对象、函数和属性。
在顶层的JavaScript代码中,可以用关键字this引用全局对象。因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来访问。
例如:当JavaScript代码应用parseInt()函数时,它引用的是全局对象parseInt属性。全局对象是作用域链的头,还意味着顶层JavaScript代码中声明的所有变量都将成为全局对象的属性。
全局对象的详细介绍:
1、可以通过this引用,在客户端JavaScript中,全局对象就是window对象
console.log(this) // window
2、全局对象是由Object构造函数实例化的一个对象
console.log(this instanceof Object) // true
3、预定了很多内置属性和函数
console.log(Math.random()) // 0.31526211617004263
console.log(this.Math.random()) // 0.31526211617004263
4、作为全局变量的宿主
var a = 1
console.log(this.a) // 1
5、客户端JavaScript中,全局对象有window属性指向自身
var a = 1
console.log(window.a)
this.window.b = 2
console.log(window.b)
总结:全局上下文中的变量对象就是全局对象
函数上下文
在函数上下文中,我们用活动对象来表示变量对象
活动对象和变量对象其实是一个东西,只是变量对象是规范上的或者说是引擎实现上的,不可在JavaScript环境中访问,只有到当进入一个执行上下文中,这个执行上下文的变量对象才会被激活,所以才叫活动对象,而只有被激活的变量对象,也就是活动对象上的各种属性才能被访问。
活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性值是Arguments对象。
执行过程
执行上下文的代码会被分为两个阶段执行:分析和执行
- 进入执行上下文
- 代码执行
进入执行上下文
当进入执行上下文是,这时候还没有执行代码
变量对象的创建依次经历以下几个过程:

1、函数的所有形参(如果是函数上下文):建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。
(1)由名称和对应值组成的一个变量对象的属性被创建
(2)如没有实参,属性值设为undefined
2、函数声明:检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。
(1)由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建
(2)如果变量对象已经存在相同名称的属性,则完全替换这个属性
3、变量声明:检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。
(1)由名称和对应值(undefined)组成一个变量对象的属性被创建
(2)如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性
例如:
function foo(a) {
var b = 2
function c() {}
var d = function(){}
b = 3
}
foo(1)
在进入执行上下文的时候,变量对象(活动对象AO)是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
}
代码执行
在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值
上面的例子,在代码执行完后,这时候变量对象是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: 3,
c: reference to function c(){},
d: reference to FunctionExpression 'd'
}
总结下上述所说:
- 全局上下文的变量对象初始化是全局对象
- 函数上下文的变量对象初始化只包括Arguments对象
- 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值
- 在代码执行阶段,会再次修改变量对象的值
在进入执行上下文时,首先会处理函数声明,其实会处理变量声明,如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。
网友评论