JS 执行上下文的一次理解
执行上下文
执行上下文概念
- 当代码运行时,会产生一个对应的执行环境,在这个环境中,变量会被事先提出来(变量提升),代码从上往下开始执行,就叫做执行上下文。
注:在定义变量是未直接赋值,使用默认值 undefined。
在 JavaScript 的世界里,运行环境有三种,分别是:
- 全局环境:代码首先进入的环境
- 函数环境:函数被调用时执行的环境
- Eval的代码 - 在Eval函数内运行的代码
执行上下文特点
-
单线程,在主进程上运行
-
同步执行,从上往下按顺序执行
-
全局上下文只有一个,浏览器关闭时会被弹出栈
-
函数的执行上下文没有数目限制
-
函数每被调用一次,都会产生一个新的执行上下文环境
执行上下文栈
执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境。处于活动状态的执行上下文环境只有一个。
执行上下文生命周期
执行上下文共分3个阶段,分别是:
-
创建阶段
1. 生成变量对象(全局对象)
2. 建立作用域链
3. 确定 this 指向
-
执行阶段
1.变量调用赋值
2.函数引用,创建新的执行上下文环境
3.执行其他代码
-
销毁阶段
执行完毕退出执行栈,等待回收被销毁
变量对象
-
变量对象是与执行上下文相关的数据作用域,存储了上下文中定义的变量和函数声明。
-
变量对象式一个抽象的概念,在不同的上下文中,表示不同的对象:
- 全局执行上下文的变量对象
-
全局执行上下文中,变量对象就是全局对象。
-
在顶层js代码中,this指向全局对象,全局变量会作为该对象的属性来被查询。在浏览器中,window就是全局对象。
- 函数执行上下文的变量对象
-
函数上下文中,变量对象VO就是活动对象AO。
-
初始化时,带有arguments属性。
-
函数代码分成两个阶段执行
-
进入执行上下文时,此时变量对象包括
-
形参
-
函数声明,会替换已有变量对象
-
变量声明,不会替换形参和函数
-
函数执行
列子
var a = 1, b, fn = function() {
console.log(a)
var a = 3,b = 2;
bar(b)
}
var bar = function(x) {
return x + 4;
}
fn()
- 执行结果 undefined
- JS 是单线程,从上到下执行每一行代码
- 创建变量a并赋值1,变量b 没有赋值,使用 undefined 默认值,fn 赋值函数,bar 赋值函数
- 调用 fn(), fn 进入执行栈,创建新的 fn 内部执行上下文。打印 a 此时 在 fn作用域内,定义了一个新的变量 a,但是在使用a是 a并没有赋值,所以 打印a, 输出:undefined。代码向下执行,a,b分别赋值。调用函数bar()
- 函数bar进入执行栈,开始执行, 返回结果,出栈内部等待销毁回收。
- fn() 退出执行栈,等待销毁回收
- 回到全局执行环境(全局上下文)