1.什么是执行上下文?
执行上下文是当前JavaScript代码被解析和执行时所在环境。在JavaScript中运行任何的代码都是在执行上下文中运行的。
2.执行上下文有三种类型:
🔷全局执行上下文
全局执行上下文:
*浏览器引擎在执行全局代码前将window确定为全局执行上下文
*对全局数据进行预处理
var定义的全局变量==>undefined,添加为window的属性
function声明的全局函数==>赋值为fun,添加为window的方法
this==>赋值为window,表示全局执行上下文
*开始执行全局代码
每次运行一个Javascript代码时,引擎都会创造一个全局执行上下文(有且仅有一个)。
var num = 2;
function pow(num) {
return num * num;
}
引擎如何读取上面的代码?
引擎:第一行,它是变量!将它存储在全局存储器中。
引擎:第二行,我看到了一个函数声明。让我们也把它存储在全局存储器中。
(
全局存储器:
全局内存包含全局变量和函数声明供以后使用。
当Javascript引擎运行你的代码时,它会创建:
全局执行上下文
全局存储器(也称为全局作用域或全局变量环境)
(
执行上下文 vs 作用域:javascript执行上下文、作用域与闭包(第四篇)-作用域与执行上下文
)
)
🔷函数执行上下文
函数执行上下文
*在调用函数,准备执行函数体之前, 创建对应的函数执行上下文对象
*对局部数据进行预处理
形参变量==>赋值(实参)==>添加为执行上下文的属性
arguments==>赋值(实参列表),添加为执行上下文的属性
*var定义的局部变量==>undefined,添加为执行上下文的属性
function声明的函数==> 赋值(fun),添加为执行上下文的方法
this==>赋值( 调用函数的对象)
*开始执行函数体代码
函数执行上下文是处于函数体内的代码解析及运行的环境,只有在函数被调用时才会被创建,每次调用函数都会创建一个新的执行上下文。函数执行上下文可以存在多个,甚至是无数个;
🔷Eval函数执行上下文
只有在eval函数中的代码才有eval函数执行上下文
3.执行上下文的生命周期:
创建过程: 1.创建变量:即初始化函数的参数arguments,提升函数及变量的声明
2.建立作用域和作用域链,
3.确定this的指向。
执行过程:1.变量赋值,2.函数引用,3.执行其他代码。
销毁阶段:执行完毕后出栈,等待被回收。
- 创建阶段:
在全局执行上下文中,this的值指向全局对象,在浏览器中,this的值➡window对象;在nodejs中指向的是➡module对象
在函数执行上下文中,this的值取决于函数的调用方式(即如何被调用的)。当它被一个引用对象调用,则将的值this设置为该对象,否则this的值设置为全局对象或undefined(在严格模式下)
4.执行上下文栈
每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。函数执行完后,栈将其环境弹出,把控制权返回给之前的执行环境。
一个程序代码中包含多个函数,也就是包含多个函数执行上下文,为了管理好多个执行上下文之间的关系,JavaScript中创建了执行上下文栈来管理执行上下文。执行上下文栈是具有后进先出结构的栈结构,用于存储在代码执行期间创建的所有执行上下文。
当JavaScript引擎运行JavaScript代码时它会创建一个全局执行上下文并将其push到当前调用栈。(函数还没解析或者是执行、调用)仅存在全局执行上下文,每当引擎发现函数调用时,引擎都会为该函数创建一个新的函数执行上下文,并将其推入到堆栈的顶部(当前执行栈的栈顶)。当引擎执行其执行上下文位于堆栈顶部的函数之后,将其对应的函数执行上下文将会从堆栈中弹出,并且控件到达当前堆栈中位于其下方的上下文(如果有下一个函数的话)