红宝书第六讲:作用域链与闭包:厨房里的调味料架原理

红宝书第六讲:作用域链与闭包:厨房里的调味料架原理

资料取自《JavaScript高级程序设计(第5版)》。 查看所有教程:红宝书学习大纲


一、什么是作用域链?(洋葱层级结构)

想象你在厨房做菜,每个调料瓶按使用频率由近到远摆放:

  1. 当前厨房台面:手边的盐、酱油 → 相当于函数内部变量(局部作用域)
  2. 冰箱里的辣椒酱:常用但稍远 → 外层函数的变量(父级作用域)
  3. 储藏室的大米:最远的储备 → 全局变量(全局作用域)

作用域链的查找顺序

javascript 复制代码
function 厨房() {
  const 盐 = "适量盐"; // 第二层作用域

  function 炒菜() {
    console.log(盐); // ✅ 能找到冰箱里的盐
    console.log(大米); // ✅ 能找到储藏室的大米
  }
  
  炒菜();
}

const 大米 = "5kg"; // 第三层(全局)
厨房();

二、闭包:私人调料罐

闭包就像你出门前把常用调料装进便携罐带走:

  • 定义:内部函数保留外部变量的引用,"保鲜"这部分变量的值。
  • 关键特点:即使外层函数已执行完毕,闭包仍然能访问其变量。

代码示例

javascript 复制代码
function 制盐机() {
  let 盐堆存量 = 1000;   // 盐堆存量被内部函数"锁住"

  return function 取盐(需要量) {
    盐堆存量 -= 需要量;  // 每次取盐减少存量
    console.log(`剩余盐量:${盐堆存量}g`);
  };
}

const 我的取盐动作 = 制盐机();
我的取盐动作(100);  // 剩余盐量:900g
我的取盐动作(200);  // 剩余盐量:700g
  • 分析制盐机()执行后,本应销毁的盐堆存量取盐函数保留,形成闭包[^3]。

三、闭包的两面性

益处

  1. 数据保护 :避免变量全局污染,如封装计数器:

    javascript 复制代码
    function 创建计数器() {
      let count = 0;
      return () => ++count; // 只能通过闭包修改
    }
    const 计数器 = 创建计数器();
    计数器(); // 1

潜在问题

  • 内存泄漏:如果闭包引用大型数据且未被释放,可能影响性能:

风险示例

javascript 复制代码
function 加载大数据() {
  const 大数据 = new Array(1000000).fill('🚗'); // 内存大户

  return function 处理函数() {
    // 即使不再需要大数据,闭包仍保留引用
  };
}
let 保存闭包 = 加载大数据();
保存闭包 = null; // ✅ 需手动解除引用

四、生活中的闭包场景

  1. 按钮点击统计:记录用户点击按钮次数。

  2. 接口请求防重复:闭包保存最后一次请求标识。

  3. 模块化开发 :借助IIFE(立即执行函数)封闭作用域:

    javascript 复制代码
    const 模块 = (function() {
      const 内部数据 = "私有";
    
      return {
        get数据: () => 内部数据
      };
    })();
    
    console.log(模块.get数据()); // '私有'

目录:总目录 上篇文章:红宝书第五讲:函数声明与表达式小白详解

总结与练习

  • 理解步骤:先画作用域层级 → 再看闭包如何抓取变量。
  • 练习:实现一个缓存计算结果的闭包函数。

重要提醒:闭包虽强大,但控制引用范围,避免内存包袱过重!

相关推荐
子兮曰6 小时前
async/await高级模式:async迭代器、错误边界与并发控制
前端·javascript·github
恋猫de小郭7 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
GIS之路9 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒10 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol11 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉11 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau11 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生11 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼11 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范
明君8799711 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter