执行上下文(Execution Context):函数执行前进行的准备工作(也称执行上下文环境)。
运行 JavaScript 代码的时候,当代码执行进入一个环境,就会为该环境创建一个执行上下文,它会在运行代码前做一些准备工作,如确定作用域,创建局部变量对象等。
JavaScript运行时首先会进入全局环境,对应会产生全局上下文。程序代码中基本都会有函数的存在,那么调用函数,就会进入函数执行上环境,对应就会产生函数的执行上下文。
JavaScript 执行环境
- 全局环境 有且只有一个
- 函数环境 可以有多个
- eval函数环境(已不推荐使用)
JavaScript中管理多个执行上下文
(栈数据结构)
遵循‘先进后出,后进先出’的规则或称LIFO(“Last In First Out”)规则
特点:
- 先进后出,后进先出
- 出口只有一个
例:
function foo() {
function
bar() {
return 'I am bar';
}
return bar();
}
foo();
那么下面代码一共有多少个上下文:
(function foo(i) {
if (i == 3) {
return;
} else {
console.log(i);
foo(++i);
}
})(0);
//全局上下文
//函数上下文0
//函数上下文1
//函数上下文2
//函数上下文
//共产生5个上下文,其中1个全局,4个函数上下文
执行上下文的生命周期
分为两个阶段:
- 创建阶段(进入执行上下文):函数被调用时,进入函数环境,为其创建一个执行上下文此时进入创建阶段。
- 执行阶段(代码执行):执行函数代码时,此时执行上下文进入执行阶段。
创建阶段的操作
1创建变量对象
- 函数环境会初始化创建 Arguments 对象,形式参数(并赋值)
- 普通函数声明(并赋值)
- 局部变量声明,函数表达式声明(未赋值)
2初始化作用域链
3确定 this 指向(this由调用者确定)
4确定作用域(词发环境决定,哪里声明定义,就在哪里确定)
执行阶段操作
.1变量对象赋值
- 变量赋值
- 函数表达式赋值
2调用函数
3顺序实现其他代码
产生函数上下文,会经历两个阶段:创建阶段、执行阶段
创建阶段:要做的事(确定变量、确定作用域链、确定this的指向)
变量对象(Arguments对象、形式参数、字面量函数声明、变量)
执行阶段:执行每一行代码
AO
如果处于当前上下文的变量对象,称为AO,如果不是处于当前上下文的变量对象,则称之为VO
例:
var x = 10;
function foo() {
var y = 20;
console.log(x + y);
}
foo(); // 30
//分析代码中的变量对象
//对于全局上下文
AO : x (10) // 变量 x 的值为 10
foo : pointer to foo() // foo 标识符指向一个函数
// 当进入 foo 函数上下文
AO : y(20)