用大白话讲明白JavaScript的作用域链

作用域链是什么?

作用域链就像是"找人帮忙的优先级列表"。当你在代码中要用到一个变量时,JavaScript引擎会按照这个列表顺序一层层查找:

  1. 先看自己手头有没有(当前作用域)

  2. 没有就问上一级领导(外层作用域)

  3. 还没有就继续往上找(更外层作用域)

  4. 直到找到全局大老板(全局作用域)

  5. 连大老板都不知道,那就报错(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
  1. 模块模式:利用函数作用域隐藏私有变量
const 我的模块 = (function() {
  // 私有区域
  const 私有变量 = "秘密";
  
  // 返回公有接口
  return {
    get秘密: function() {
      return 私有变量; // 通过闭包访问
    }
  };
})(); // 立即执行

console.log(我的模块.get秘密()); // "秘密"
console.log(私有变量); // 报错:私有变量不存在


类似现代写法

class 我的模块 {
  #私有变量 = "秘密"; // 私有字段
  
  get秘密() {
    return this.#私有变量;
  }
}

const 实例 = new 我的模块();
console.log(实例.get秘密()); // "秘密"
console.log(实例.#私有变量); // 报错
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容