「JavaScript深入」一文说明白JS的执行上下文与作用域
JavaScript深入 — 执行上下文与作用域
- 上下文
- 执行上下文
- 生命周期
- 创建阶段
- 执行阶段
- 回收阶段
- 执行栈
- 作用域链
- 作用域
- 词法作用域(静态作用域)
上下文
变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。 每个上下文都有一个关联的变量对象,而这个上下文中定义的所有变量和函数都存在于这个对象上。
全局上下文是最外层的上下文,(在浏览器中,全局上下文就是我们常说的 window 对象,因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法)上下文在其所有代码都执行完毕后会被销毁,包括它上面的变量和函数。
每个函数调用都有自己的上下文。当代码执行流入函数时,函数的上下文被推到一个上下文栈上。在函数执行完之后,上下文栈会弹出该函数的上下文,将控制权返回给之前的执行上下文。
执行上下文
简单的来说,执行上下文是一种对JavaScript代码执行环境的抽象概念,也就是说,只要有JavaScript代码运行,那么它就一定是运行在执行上下文中,变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。
执行上下文的类型分为三种:
- 全局执行上下文:只有一个,浏览器中的全局对象就是
window对象,this指向这个全局对象 - 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文
Eval函数执行上下文:指的是运行在eval函数中的代码,很少用而且不建议使用
🌰 简单举例如下:

紫色框住的部分为全局上下文,蓝色和橘色框起来的是不同的函数上下文。只有全局上下文(的变量)能被其他任何上下文访问
可以有任意多个函数上下文,每次调用函数创建一个新的上下文,会创建一个私有作用域,函数内部声明的任何变量都不能在当前函数作用域外部直接访问
生命周期
执行上下文的生命周期包括三个阶段:创建阶段->执行阶段->回收阶段
创建阶段
创建阶段即当函数被调用,但未执行任何内部代码之前
- 确定
this的值,也被称为This Binding - 词法环境(LexicalEnvironment)组件被创建
- 变量环境(VariableEnvironment)组件被创建
// 伪代码
ExecutionContext = {ThisBinding = <this value>,LexicalEnvironment = { ... },VariableEnvironment = { ... },
}
This Binding
this 的值是在执行时候才能确认,定义时不能确认
词法环境
词法环境有两个组成部分:
- 全局环境:是一个没有外部环境的词法环境,其外部环境引用为
null,有一个全局对象,this的值指向这个全局对象 - 函数环境:用户在函数中定义的变量被存储在环境记录中,包含了
arguments对象,外部环境的引用可以是全局环境,也可以是包含内部函数的外部函数环境
// 伪代码
GlobalExectionContext = { // 全局执行上下文LexicalEnvironment: { // 词法环境EnvironmentRecord: { // 环境记录Type: "Object", // 全局环境// 标识符绑定在这里 outer: <null> // 对外部环境的引用} }
}
FunctionExectionContext = { // 函数执行上下文LexicalEnvironment: { // 词法环境EnvironmentRecord: { // 环境记录Type: "Declarative", // 函数环境// 标识符绑定在这里 outer: <Global or outer function environment reference> // 对外部环境的引用} }
}
变量环境
变量环境也是一个词法环境,因此它具有上面定义的词法环境的所有属性
在ES6中,词法环境和变量环境的区别在于前者用于存储函数声明和变量(let 和 const )绑定,而后者仅用于存储变量(var)绑定
执行阶段
在这阶段,执行变量赋值、代码执行
如果JavaScript引擎在源代码中声明的实际位置找不到变量的值,那么将为其分配undefined
回收阶段
执行上下文出栈等待虚拟机回收执行上下文
执行栈
执行栈,也叫调用栈,后进先出,用于存储在代码执行期间创建的所有执行上下文

当Javascript引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中
每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中
引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文
🌰 举个例子:
let a = 'Hello World!';
function first() {console.log('Inside first function');second();console.log('Again inside first function');
}
function second() {console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');
🫱 输出结果:
Inside first function
Inside second function
Again inside first function
Inside Global Execution Context
👇 执行栈中内容用图表示:

作用域链
上下文中的代码在执行时,会创建变量对象的一个作用域链。这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。
从执行上下文的角度来说: 作用域链是由当前执行上下文和所有外层执行上下文的变量对象组成的链式结构。当JavaScript代码在一个执行上下文中查找变量时,会先在当前执行上下文的变量对象中查找,如果没有找到,就会继续在外层执行上下文的变量对象中查找,直到找到该变量或者到达全局执行上下文。
如果上下文是函数,则其活动对象用作变量对象,活动对象最初只有一个定义变量:arguments。
代码正在执行的上下文的变量对象始终位于作用域链的最前端,全局上下文的变量对象始终是作用域链的最后一个变量对象。
var color = "blue";function changeColor() {if(color === "blue"){color = "red";} else {color = "blue";}
}
👆 如上例子,函数 changeColor() 的作用域链包含两个对象:一个是它自己的变量(定义了 arguments 对象),另一个是全局上下文的变量对象。

上图矩形表示不同的上下文。内部上下文可以通过作用域链访问外部上下文中的一切。
上下文之间的连接是线性的,有序的。每个上下文都可以到上一级上下文中去搜索变量和函数。

函数执行完毕后,局部活动对象会被销毁,内存中就只剩下全局作用域。
作用域
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。——《你不知道的JavaScript》
词法作用域(静态作用域)
作用域共有两种工作模型。第一种是最为普遍的,被大多数编程语言所采用的词法作用域,意味着作用域是由书写代码时函数声明的位置来决定的。编译时就基本能够知道全部标识符在哪里以及是如何声明的,从而能够在执行过程中对它们进行查找。
var value = 1;function foo() {console.log(value);
}
function bar() {var value = 2;foo();
}bar(); // 1
// 在函数定义的时候确定的作用value等于1 所以调用的时候也等于1
另一种叫作动态作用域,最常见的就是Bash脚本。
#test.sh
name='lily';function getName() {echo name: $name;
}function getMyName() {local name='lucy';getName;
}getMyName;
如上代码,如果是静态作用域,函数的作用域在定义时就确定了,输出应为“lily”,而Bash是动态作用域,所以其实输出的是“lucy”。
相关文章:
「JavaScript深入」一文说明白JS的执行上下文与作用域
JavaScript深入 — 执行上下文与作用域 上下文执行上下文生命周期创建阶段执行阶段回收阶段 执行栈作用域链作用域词法作用域(静态作用域) 上下文 变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。 每个上下文都有一个关联的…...
Qt C++设计模式->组合模式
组合模式(Composite Pattern)是一种结构型设计模式,允许你将对象组合成树形结构以表示部分与整体的层次关系。组合模式使得客户端可以以统一的方式对待单个对象和组合对象,简化了对复杂树形结构的操作。 组合模式的应用场景 组合…...
Acwing Bellman-Ford SPFA
1. Bellman-Ford 该算法适用于有负权边的情况,注意:如果有负权环的话,最短路就不一定存在了。时间复杂度 O ( m n ) . O(mn). O(mn).该算法可以求出来图中是否存在负权回路,但求解负权回路,通常用SPFA算法,…...
我能禁止使用某协议的ip禁止访问我的资源吗
是的,你可以禁止使用某个协议的IP地址访问你的资源。这种操作通常涉及网络防火墙、服务器配置或应用程序设置,具体方法取决于你的网络环境和使用的技术。以下是一些常见的实现方法: 1. 使用防火墙 大多数防火墙(硬件或软件&…...
快速理解TCP协议(二)——TCP协议中的拥塞控制机制详解
在计算机网络中,TCP(传输控制协议)是一种广泛使用的面向连接的、可靠的、基于字节流的传输层通信协议。TCP协议通过一系列复杂的机制来确保数据的可靠传输,其中拥塞控制是至关重要的一环。本文将深入探讨TCP协议中的拥塞控制机制&…...
Linux:debug: systemtap: ubacktrace
https://docs.huihoo.com/systemtap/sourceware.org/systemtap/SystemTap_Beginners_Guide/ustack.html 这个函数可以帮助将user level的backtrace打印出来。 stap -d /bin/ls --ldd \ -e probe process("ls").function("xmalloc") {print_usyms(ubacktra…...
使用AI进行需求分析的案例研究
生成式 AI 的潜在应用场景似乎无穷无尽。虽然这令人兴奋,但也可能让人不知所措。因此,团队在使用这项技术时需要有明确的目标:关键是要明确生成式 AI 在团队工作中能产生哪些实质性影响。 在软件工程中,一个引人注目的应用场景是…...
Python内置的re库
Python内置的re库是专门用于处理正则表达式的标准库。它提供了一系列函数和类,使得在Python程序中可以使用正则表达式进行字符串的搜索、替换、分割等操作。re库的使用非常广泛,几乎任何需要复杂文本处理的场景都可以用到它。 主要函数 1、complie函数…...
毕业设计选题:基于ssm+vue+uniapp的面向企事业单位的项目申报小程序
开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…...
jQuery 简介⑤属性操作
九、属性操作 jQuery的属性操作方法一览表 $("selector").val(); // 获取第一个匹配元素的value值(一般用于表单控("selector").val("Hello"); // 设置所有匹配元素的value值为"Hello" $("selector").html();// 获取第一个…...
[Linux] Linux操作系统 进程的状态
标题:[Linux] Linux操作系统 进程的状态 个人主页:水墨不写bug (图片来源于网络) 目录 一、前置概念的理解 1.并行和并发 2.时间片 3.进程间具有独立性 4.等待的本质 正文开始: 在校的时候,你一定学过《…...
深入解析Python 中的 sortedcontainers 库:高效的排序数据结构
在日常的 Python 编程中,列表(list)、集合(set)和字典(dict)是常用的数据结构。然而,在某些特定的场景下,我们需要对数据进行排序,并且希望在插入、删除或访问…...
什么是服务器日志,日志有什么作用?
前言 服务器日志是指服务器等电脑设备或软件的运作记录。这些日志记录了服务器接收客户端处理请求的过程以及服务器对这些请求的处理结果。服务器日志对于排查和解决计算机系统和网络应用中的问题至关重要,因为它们包含了用于调试问题的消息、服务器状态以及其他…...
Codeforces Round 971 (Div. 4)A-G1题解
Codeforces Round 971 (Div. 4) A 就是b - a #include <bits/stdc.h> #define int long longusing namespace std;void solve() {int a, b;cin >> a >> b;cout << b - a << endl; }signed main() {ios::sync_with_stdio(false);cin.tie(0);co…...
QT----基于QML的计时器
赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库,可以对比文档和提交记录学习起来更清晰 QT-Timer 学习使用c的listmodel 学习使用了如何用c的listmodel来存储数据. 新建一个TImeListModel类继承自QAbstractListModel c…...
Stable Diffusion的高分辨率修复(Hires.fix)
Stable Diffusion的高分辨率修复(Hires.fix)是一项重要的功能,它旨在提高生成图像的分辨率和细节,从而使画面变得更加清晰和精细。以下是关于Stable Diffusion高分辨率修复(Hires.fix)的详细解释࿱…...
智慧体育馆可视化:实时监控与智能管理
利用图扑可视化技术实现对体育馆的实时监控和数据分析,提升运营效率、观众体验和安全管理水平,打造智能化场馆环境。...
【NLP】基于“检测器-纠错器”中文文本纠错框架
前言 许多方法将中文拼写纠正(检测和纠正给定中文句子中的错误字符)视为序列标注任务,并在句子对上进行微调。一些方法使用错误检测器作为初步任务,然后将检测结果用于辅助后续的错误纠正过程。然而,现有方法在使用检…...
vue 中加载 Mapbox GL JS Examples
Mapbox GL JS 示例 1. Mapbox GL JS的基础使用2. style 的使用2.1. 切换 style2.2. 配置一个第三方 style (添加一个Layer)2.3. 配置一个带有 slot 的 style2.4. 创建一个自定义 style 的 layer 类实现 WebGL 内容2.5. 添加Marker2.6. 添加 geojson 格式…...
Vue3 中组件传递 + css 变量的组合
文章目录 需求效果如下图所示代码逻辑代码参考 需求 开发一个箭头组件,根据父组件传递的 props 来修改 css 的颜色 效果如下图所示 代码逻辑 代码 父组件: <Arrow color"red" />子组件: <template><div class&…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
