前言
本文我们将通过解析 JavaScript 中最简单的一条语句 var a = 1;,来了解作用域有关的概念与知识,并且初步了解代码工作的三巨头 --- JS 引擎、编译器、作用域。
在阅读这篇文章前你需要了解的一些小知识:
- 作用域链:作用域链顾名思义,就是一条链子,当前作用域找不到就顺着链子往父级作用域找,最终找到全局作用域,再找不到就则会抛出一个
ReferenceError错误。也可以理解为一个函数被定义在另一个函数内部,那么内部函数的作用域链就会包含外部函数的作用域。这种结构允许内部函数访问外部函数的作用域中的变量。
var a = 1;
function foo1() {
var b = 2;
function foo2() {
var c = 3;
console.log(a)
console.log(b)
console.log(c)
}
foo2()
}
foo1()//输出1,2,3
- 变量:在 JavaScript 中,变量并不是孤立存在的,而是属于某个特定的作用域。而作用域在编译阶段就已经确定了。
- 编译阶段和执行阶段、RHS和LHS:请看文章# 了解JS中的两个阶段,编译阶段和执行阶段
JS的执行机制:
首先我们来分析一下这条代码var a = 1的底层原理是什么?
这串代码可以拆分为两部分:
var a;即声明了一个变量 aa = 1;对 a 进行赋值为 1
这两部分平平无奇,但是我们不禁思考,为什么要这样拆分呢?到底有什么作用呢?到底有哪些东西在为这串代码服务呢?
这里我们就要引入几个概念,即 JS 引擎、编译器、作用域,为了让你更加容易理解这三者之间的关系,我们用CEO(首席执行官),CTO(首席技术官),COO(首席运营官)来模拟这三者。
假设我们有一个软件开发公司,正在开发一个复杂的 Web 应用程序。在这个过程中,JavaScript 引擎、编译器和作用域分别对应公司的 CEO、CTO 和 COO。
CEO - JavaScript 引擎
- 角色:CEO 是公司的最高管理者,负责整体战略和决策。在 JavaScript 中,JavaScript 引擎就像是 CEO,负责解析和执行代码,确保应用程序的顺利运行。
- 职责:
- 解析代码:读取和理解 JavaScript 代码,类似于 CEO 分析市场和业务需求。
- 执行程序:根据解析的结果,执行代码中的各项操作,确保每个功能模块按计划运行,类似于 CEO 监督公司各个部门的运作。
- 性能优化:优化代码执行的效率,确保应用程序响应迅速,类似于 CEO 通过战略调整提升公司整体效率。
CTO - 编译器
- 角色:CTO 负责公司的技术创新和技术发展战略。在 JavaScript 中,编译器就像是 CTO,负责将源代码转换成高效的机器码,确保代码的执行速度和质量。
- 职责:
- 语法检查:在代码执行前,检查代码的语法是否正确,类似于 CTO 确保技术方案的可行性。
- 代码转换:将高级语言的代码转换成低级语言的机器码,类似于 CTO 将抽象的技术概念转化为具体的实施方案。
- 性能优化:通过各种优化技术,提高代码的执行效率,类似于 CTO 通过技术创新提升产品的竞争力。
COO - 作用域
- 角色:COO 负责公司的日常运营管理,确保各个部门高效协作。在 JavaScript 中,作用域就像是 COO,负责管理变量和函数的可见性和生命周期,确保代码的有序性和安全性。
- 职责:
- 变量管理:定义和管理变量的可见范围,确保变量在适当的时间和地点被访问和修改,类似于 COO 管理公司资源,确保各部门高效协作。
- 生命周期管理:控制变量和函数的生命周期,确保资源的合理分配和回收,类似于 COO 优化公司流程,确保资源的有效利用。
- 避免冲突:防止变量名冲突,确保代码的清晰和安全,类似于 COO 协调各部门的工作,避免冲突和重叠。
假设我们要编写一个简单的 JavaScript 函数:
function foo() {
var a = 1;
}
- JS 引擎(CEO):当你运行这段代码时,JavaScript 引擎(CEO)开始解析和执行这段代码。它会调用
foo函数。 - 编译器(CTO):在执行之前,编译器(CTO)会先检查这段代码是否有语法错误,并将其转换成计算机可以理解的指令,并且声明了一个类型为
undefined的全局变量a,而这一行为在编译阶段进行。 - 作用域(COO):在这个例子中,
a变量的作用域是在foo函数内部。这意味着它们只在foo函数内可用,类似于 COO 管理公司资源,确保每个部门的资源在适当的时间和地点被使用,而在执行阶段进行了一个LHS,查找到了a并且进行赋值确定了a的数据类型为number
因此,我们可以重新解释一下var a = 1;这串代码:
在编译阶段,编译器对var a = 1;进行分词,并且声明了一个全局变量,名称为 a 且类型为undefined,并将其转换成计算机可以理解的指令,传输给了JS 引擎 ,到了执行阶段,进行了一个LHS查找,查找到了 a 并且进行赋值确定了 a 为number,而查找过程中遵守作用域的规则(作用域链),先查找当前作用域-->外层...-->全局-->未找到,停止,如果中途找到了,立马停止。
是不是刷新了一下你对于这串基础到不能再基础的代码的认知了呢,这段解释一出去,了解不够透彻的人可是会晕晕的哦~
小结:
我们了解了代码工作的三巨头 --- JS 引擎、编译器、作用域,及其作用与在代码运行时所承担的任务,以及更深入的解释了代码的基础原理。
---欢迎各位点赞、收藏、关注,如果觉得有收获或者需要改进的地方,希望评论在下方,不定期更新