本文从底层原理剖析JavaScript作用域链,解析[[Scopes]]属性如何存储执行期上下文。通过图解全局函数与嵌套函数的定义及激活过程,展示变量沿作用域链向上查找的机制,阐明外部无法访问内部变量的根本原因。
前言
在JavaScript学习过程中,开发者通常知晓外部作用域无法直接访问内部变量的基本规则。然而,支撑这一规则的具体底层实现机制往往被忽视。本文旨在从基础视角出发,深入解析作用域链的工作机制,为读者提供清晰的技术理解。
作用域
1.什么是作用域
作用域(Scope)本质上是基于名称查找变量的一套规则体系。通俗而言,它可以被视为一个封闭的空间:该空间内部对外部不可见,外部无法直接访问内部变量;但内部空间可以访问包裹它的外部空间中的变量。
2.[[Scopes]]属性
在JavaScript中,函数被视为对象。对象包含可访问和不可自由访问的属性,其中[[Scopes]]属性属于后者,该属性仅允许JavaScript引擎内部读取。
所谓的[[scope]]即我们日常提及的作用域,其内部存储了运行期上下文对象的集合。
由于func.prototype.constructor与func指向同一函数对象,此处通过访问函数func的原型对象来展示[[Scopes]]属性。

3.作用域链
[[scope]]属性中存储的执行期上下文对象集合呈现链式连接结构,这种结构被称为作用域链。JavaScript引擎正是依靠作用域链来解析变量,其查找策略是沿作用域链从顶端依次向下查询(即在当前函数内部查找对象时,仅在该函数的作用域链中进行检索)。
4.图解查找变量原理
//以如下代码为例说明JavaScript通过作用域链查找变量的原理**
function a() {
function b() {
//这里原来我给的b的值是234,后面经过评论区提醒后面的图写的是123,所以我将b的值改为了123
var b = 123;
}
var a = 123;
b();
}
var glob = 100;
1.当全局函数a()被定义时,其作用域链结构如下所示。

此时,函数的[[Scopes]]属性指向作用域链对象。该作用域链仅包含一个键值对,该键值对指向全局对象。全局对象存储了全局范围内可访问的资源,即最外层作用域,所有代码均可访问。
2.当全局函数a()被激活并调用时,作用域链结构发生变化。

此时,作用域链中首先可访问的是Activation Object(激活对象)中的键值对;若其中未找到目标,则继续访问全局对象。
3.在函数a()内部定义函数b时,函数b的作用域链结构如下。

当函数b仅被定义而未被调用时,其作用域链与函数a保持一致。
4.当函数a()内部的函数b被激活调用时,作用域链结构再次更新。

此时,作用域链首先指向函数b()的Activation Object。变量查找遵循作用域链顺序进行,一旦找到目标变量即停止搜索。
总结
外部作用域无法访问内部作用域的根本原因在于:外部作用域的作用域链中不包含内部作用域的Activation Object,因此无法访问内部变量。内部作用域访问变量的顺序遵循作用域链规则:优先从内部查找,若未找到则沿作用域链向外层查找,直至全局作用域。
本文介绍了JavaScript作用域链的底层原理,更多相关JavaScript作用域链内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!