目录
执行上下文与执行栈
引言
对于我们前端开发者来说理解JS程序内部执行机制是必要的,其中一个关键概念就是Js的执行上下文和执行栈。
执行上下文是JS语言较为底层的知识,学习掌握有助于我们更深入的把握JS这门语言的本质,也有助于理解作用域、闭包、变量提升等相关知识。
什么是执行上下文?
代码执行前,浏览器的Js引擎先会创建代码执行的环境来处理此Js代码的转换和执行,代码的执行环境称为执行上下文。
执行上下文是一个抽象概念,包含当前正在运行的代码以及当前执行环境中的变量、函数声明,参数(arguments),作用域链,this等信息。
一句话概括:执行上下文就是javascript代码被解析和执行时所在环境的抽象概念。
执行上下文生命周期
(1)创建阶段
生成变量对象、建立作用域链、确定this的指向
(2)执行阶段
变量赋值、函数的引用、执行其他代码
变量对象
变量对象是与执行上下文相关的数据作用域,存储了上下文中定义的变量和函数声明 变量对象是一个抽象的概念,在全局执行上下文中,变量对象就是全局对象。 在顶层js代码中,this指向全局对象,全局变量会作为该对象的属性来被查询。在浏览器中,window就是全局对象
执行上下文的类型
在js中,执行上下文分为以下三种:
- 全局执行上下文:只有一个,也就是浏览器对象(即window对象),this指向的就是这个全局对象。
- 函数执行上下文:有无数个,只有在函数被调用时才会被创建,每次调用函数都会创建一个新的执行上下文。
- Eval函数执行上下文:js的eval函数执行其内部的代码会创建属于自己的执行上下文, 很少用而且不建议使用。
对于每个执行上下文,都有三个重要属性:变量对象、作用域链(Scope chain)、this
执行上下文的特点
- 单线程,只在主线程上运行;
- 同步执行,从上向下按顺序执行;
- 全局上下文只有一个,也就是window对象;
- 函数执行上下文没有限制;
- 函数每调用一次就会产生一个新的执行上下文环境。
执行栈
是一种先进后出的数据结构,用来存储代码运行的所有执行上下文
- 当 JS 引擎第一次遇到js脚本时,会创建一个全局的执行上下文并且压入当前执行栈
- 每当JS 引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部
- 当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文
- 一旦所有代码执行完毕,JS 引擎从当前栈中移除全局执行上下文
执行栈示例
var a = 1; // 1. 全局上下文环境
function bar (x) {
console.log('bar')
var b = 2;
fn(x + b); // 3. fn上下文环境
}
function fn (c) {
console.log(c);
}
bar(3); // 2. bar上下文环境