你真的懂js的执行上下文吗?(详细说明js的执行过程)
myzbx 2025-07-23 16:44 5 浏览
JavaScript执行上下文
目录
- JavaScript执行上下文
- 前言概念执行上下文的特点JS如何管理多个执行上下文执行栈执行上下文的生命周期创建阶段This Binding词法环境变量环境 执行阶段销毁阶段
前言
在编程这个行业中总是能听到这个词“执行上下文”。那么什么叫“执行上下文”呢?
本篇文章主要是介绍javascript中的执行上下文, 看完之后你可以了解到:
- 执行上下文的类型
- 执行上下文特点
- 执行栈
- 执行上下文的生命周期
概念
首先我们来介绍什么是“执行上下文”.
举个例子,生活中,相同的话在不同的场合说可能会有不同的意思,而这个说话的场合就是我们说话的语境。
同样对应在编程中, 对程序语言进行“解读”的时候,也必须在特定的语境中,这个语境就是javascript中的执行上下文。
一句话概括:
执行上下文就是javascript代码被解析和执行时所在环境的抽象概念。
执行上下文的类型
在js中,执行上下文分为以下三种:
- 全局执行上下文:只有一个,也就是浏览器对象(即window对象),this指向的就是这个全局对象。
- 函数执行上下文:有无数个,只有在函数被调用时才会被创建,每次调用函数都会创建一个新的执行上下文。
- Eval函数执行上下文:js的eval函数执行其内部的代码会创建属于自己的执行上下文, 很少用而且不建议使用。
执行上下文的特点
- 单线程,只在主线程上运行;
- 同步执行,从上向下按顺序执行;
- 全局上下文只有一个,也就是window对象;
- 函数执行上下文没有限制;
- 函数每调用一次就会产生一个新的执行上下文环境。
JS如何管理多个执行上下文
通过上面介绍,我们知道了js代码在运行时可能会产生无数个执行上下文,那么它是如何管理这些执行上下文的呢?
同时由于js是单线程的,所以不能同时干两件事,必须一个个去执行,那么这么多的执行上下文是按什么顺序执行的呢?
执行栈
接下来就对上面的问题做出解答,管理多个执行上下文靠的就是执行栈,也被叫做调用栈。
特点:后进先出(LIFO)的结构。
作用:存储在代码执行期间的所有执行上下文。
(LIFO: last-in, first-out,类似于向乒乓球桶中放球,最先放入的球最后取出)
- js在首次执行的时候,会创建一个全局执行上下文并推入栈中。
- 每当有函数被调用时,引擎都会为该函数创建一个新的函数执行上下文然后推入栈中。
- 当栈顶的函数执行完毕之后,该函数对应的执行上下文就会从执行栈中pop出,然后上下文控制权移到下一个执行上下文。
比如下面的一个例子:
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上下文环境
如下图:
执行上下文的生命周期
执行上下文的生命周期也非常容易理解, 分为三个阶段:
- 创建阶段
- 执行阶段
- 销毁阶段
创建阶段
在创建阶段, 主要有是有这么几件事:
- 确定this的值, 也就是绑定this (This Binding);
- 词法环境(LexicalEnvironment)组件被创建;
- 变量环境(VariableEnvironment)组件被创建.
一张图方便你理解
用伪代码来实现:
ExecutionContext = {
ThisBinding = <this value>, // 确定this
LexicalEnvironment = { ... }, // 词法环境
VariableEnvironment = { ... }, // 变量环境
}
This Binding
通过上面的介绍我们知道实际开发主要用到两种执行上下文为全局和函数, 那么绑定this在这两种上下文中也不同.
- 全局执行上下文中, this指的就是全局对象, 浏览器环境指向window对象, nodejs中指向这个文件的module对象.
- 函数执行上下文较为复杂, this的值取决于函数的调用方式. 具体有: 默认绑定、隐式绑定、显式绑定、new绑定、箭头函数.
词法环境
如上图, 词法环境是由两个部分组成的:
- 环境记录: 存储变量和函数声明的实际位置;
- 对外部环境的引用: 用于访问其外部词法环境.
同样的, 词法环境也主要有两种类型:
- 全局环境: 拥有一个全局对象(window对象)及其关联的所有属性和方法(比如数组的方法splice、concat等), 同时也包含了用户自定义的全局变量. 但是全局环境中没有外部环境的引用, 也就是外部环境引用为null.
- 函数环境: 用户在函数中自定义的变量和函数存储在环境记录中, 包含了arguments对象. 而对外部环境的引用可以是全局环境, 也可以是另一个函数环境(比如一个函数中包含了另一个函数).
继续用伪代码来实现:
GlobalExectionContext = { // 全局执行上下文
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 环境记录
Type: "Object" // 全局环境
// 标识符绑定在这里
},
outer: <null> // 外部环境引用
}
}
FunctionExectionContext = { // 函数执行上下文
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 环境记录
Type: "Object", // 函数环境
// 标识符绑定在这里
},
outer: <Global or FunctionEnvironment> // 外部环境引用
}
}
变量环境其实也是一个词法环境, 因此它具有上面定义的词法环境的所有属性.
在 ES6 中,词法 环境和 变量 环境的区别在于前者用于存储函数声明和变量( let 和const)绑定,而后者仅用于存储变量( var )绑定。
案例:
var a;
var b = 1;
let c = 2;
const d = 3;
function fn (e, f) {
var g = 4;
return e + f + g;
}
a = fn(10, 20);
执行上下文如下:
GlobalExectionContext = { // 全局执行上下文
ThisBinding: <Global Object>,
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 环境记录
Type: "Object", // 全局环境
c: < uninitialized >,
d: < uninitialized >,
fn: < func >
},
outer: <null> // 外部环境引用
},
VariableEnvironment: { // 变量环境
EnvironmentRecord: { // 环境记录
Type: "Object",
a: < uninitialized >,
b: < uninitialized >
},
outer: <null>
}
}
FunctionExectionContext = { // 函数执行上下文
ThisBinding: <Global Object>, // this绑定window, 因为调用fn的是window对象
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 环境记录
Type: "Object", // 函数环境
Arguments: { 0: 10, 1: 20, length: 2 }
},
outer: < GlobalLexicalEnvironment > // 全局环境的引用
},
VariableEnvironment: { // 变量环境
EnvironmentRecord: { // 环境记录
Type: "Object",
g: < uninitialized >
},
outer: < GlobalLexicalEnvironment > // 全局环境的引用
}
}
AI写代码js
因此我们可以知道变量提升的原因是:
在创建阶段,函数声明存储在环境中,而变量会被设置为 undefined(在 var 的情况下)或保持未初始化(在 let 和 const 的情况下)。所以这就是为什么可以在声明之前访问 var 定义的变量(尽管是 undefined ),但如果在声明之前访问 let 和 const 定义的变量就会提示引用错误的原因。这就是所谓的变量提升。
执行阶段
执行阶段主要做三件事情:
- 变量赋值
- 函数引用
- 执行其他的代码
注:
如果 Javascript 引擎在源代码中声明的实际位置找不到 let 变量的值,那么将为其分配 undefined 值。
销毁阶段
执行完毕出栈,等待回收被销毁
相关推荐
- 下一代EUV光刻机,万事俱备?(下一代光刻技术)
-
光刻机在半导体领域一向是个热门话题,这个能一次又一次突破工艺极限的设备仿佛一个时光机器,连接着芯片的现在和未来。从ASML宣布将推出下一代光刻机开始,人们的目光就从当前最新一代的0.33NA光刻系...
- 鸿蒙NEXT-状态管理V1和状态管理V2的差别
-
1.在V2中没有了@Link,来进行父组件和子组件的双向绑定。所以我们需要在子组件中通过@Event,调用父组件的事件,来实现装饰回调(白话来讲就是:子组件调用@Event装饰的函数,传入参数,修改父...
- 15个Excel工作表技巧,效率必备,办公必备
-
在数据的统计分析中,最常用的办公软件就是Office中的Excel,如果你对Excel的应用技巧掌握较少,可以从学习本文开始。一、Excel工作表技巧:锁定标题行方法:将光标定位到标题行下面的任意单...
- 苹果这个新的稳定平台适合用户/开发者测试
-
苹果好低调地就发布了这个平台,还好我们没有错过。从今天起你将有一种新的、更简便的方式去了解,Safari和其他使用Webkit的应用中将有什么特性和完善。SafariTechnologyPr...
- 教程|PPT绘制箭头最全攻略,收藏一下
-
微信公众号:有宝物的柜子编辑:落水无波2020-05-02原创由于没有较好的方向,公众号的更新一直暂停,根据昨天的留言,今天更新一篇关于绘制各类箭头的PPT教程,希望帮到需要的同学。那么,我们从最简...
- 老板让我制作动态图表,我不会,同事说用vlookup函数3步就搞定了
-
大家好,动态图表你会制作吗?是不是觉得动态图表制作起来应该非常的麻烦?其实并不是,大家熟悉的vlookup函数就可以用来制作动态图表,操作也非常的简单,下面就让我们来一起操作下吧COLUMN函数在这里...
- ES6(ECMAScript 2015)主要特性一览
-
下面按“语法糖”“新数据类型/API”“异步&迭代”三大类,总结ES6的核心要点。---##一、语法糖-块级作用域:`let`、`const`-`let`:声明块级变量,不可...
- Excel工作表中F1—F12应用技巧解读,再不会就Out了
-
键盘中,有一组非常显眼的功能键,就是F1—F12,其功能非常的强大,在Excel工作表中也有特别重要的作用,通过本文的学习,相信你一定有所了解。一、Excel工作表功能键:F1。功能:打开帮助对话框...
- es6的模块和核心语法(es6模块化的语法)
-
目标:通过本教案,将掌握ES6的核心语法和模块化概念,理解解构表达式的用法,并初步了解Node.js的使用,为学习Vue3打下坚实的基础。学习内容:ES6核心语法模块化解构表达式Nod...
- ECMAScript标准制定过程展示及ES7新特性披露
-
2015年6正式发布的ES6是ECMAScript的最新版本,它的发布具有里程碑意义,不仅带来了众多的新特性,而且自此将改变ECMAScript的发布策略。本文将会介绍ECMAScript标准的最新...
- 冲激函数的理解(冲激函数的性质有哪些问题)
-
一、冲激函数是什么?1.通俗理解想象一根理想化的针:长度无限小(宽度为0)高度无限大(强度无限)但总面积(能量)=1这就是冲激函数δ(t)!类比:用针尖瞬间触碰水面→产生一个无限高但宽度为...
- 前端常见面试 - 请求篇(前端面试经典问题)
-
对于前端来说,请求是前端日常工作必备的,通过请求才能与后端进行数据交互,尤其在现在前后端分离的开发模式下,请求显得就更加重要。因此,对于前端开发者来说,掌握请求就很重要。下面将从http请求和常见...
- 不会js中原型、原型链与constructor到底是什么?
-
关注我:知码前端,获取更多前端知识~~~前言哇呀呀~我说寒山说哭我带你出我敬滴酒带你出我欲成冰再也无退路怎舍寒冰冰冻我心哭~~~Hello,广大的前端小伙伴们,又到了写文章的时候,我们说一下在...
- 你真的懂js的执行上下文吗?(详细说明js的执行过程)
-
JavaScript执行上下文目录JavaScript执行上下文前言概念执行上下文的特点JS如何管理多个执行上下文执行栈执行上下文的生命周期创建阶段ThisBinding词法环境变量环境执行阶段销...
- 停止滥用箭头函数:这5个场景请务必使用 function
-
自ES6问世以来,箭头函数(ArrowFunctions)以其简洁的语法和对this的词法绑定,迅速成为了JavaScript开发者的“新宠”。我们似乎倾向于在任何可以使用函数的地方都换...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)