作用域链是什么?
作用域链就像是"找人帮忙的优先级列表"。当你在代码中要用到一个变量时,JavaScript引擎会按照这个列表顺序一层层查找:
先看自己手头有没有(当前作用域)
没有就问上一级领导(外层作用域)
还没有就继续往上找(更外层作用域)
直到找到全局大老板(全局作用域)
连大老板都不知道,那就报错(ReferenceError)
实际代码例子
// 公司仓库(全局作用域)
const 公司笔 = "红色签字笔";
function 部门A() {
// 部门储备
const 部门笔 = "蓝色圆珠笔";
function 员工小明() {
// 个人抽屉
const 个人笔 = "铅笔";
console.log(个人笔); // 先找自己 → "铅笔"
console.log(部门笔); // 自己没有 → 找部门 → "蓝色圆珠笔"
console.log(公司笔); // 自己和部门都没有 → 找公司 → "红色签字笔"
console.log(不存在的东西); // 报错:找不到!
}
员工小明();
}
部门A();
关键特点
由内向外查找:总是从当前作用域开始,往外层找
静态作用域:查找关系在代码写好的时候就确定了(词法作用域)
与执行上下文相关:每次调用函数都会创建新的作用域链
微信图片_20250710151323.png
常见应用场景
闭包: 内部函数记住了外层作用域
function 创建计数器() {
let count = 0;
return function() {
return ++count; // 记住了count变量
};
}
const 计数器 = 创建计数器();
console.log(计数器()); // 1
console.log(计数器()); // 2
- 模块模式:利用函数作用域隐藏私有变量
const 我的模块 = (function() {
// 私有区域
const 私有变量 = "秘密";
// 返回公有接口
return {
get秘密: function() {
return 私有变量; // 通过闭包访问
}
};
})(); // 立即执行
console.log(我的模块.get秘密()); // "秘密"
console.log(私有变量); // 报错:私有变量不存在
类似现代写法
class 我的模块 {
#私有变量 = "秘密"; // 私有字段
get秘密() {
return this.#私有变量;
}
}
const 实例 = new 我的模块();
console.log(实例.get秘密()); // "秘密"
console.log(实例.#私有变量); // 报错