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

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

资料取自《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数据()); // '私有'

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

总结与练习

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

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

相关推荐
Codiggerworld3 小时前
Chrome DevTools 隐藏神技:这 5 个调试技巧你可能从来没用过
前端·chrome·chrome devtools
旋生万物3 小时前
【终极实战】用Python从零“生成“一个宇宙:螺旋干涉模型的代码实现
开发语言·前端·人工智能·react.js·php·wpf
IT_陈寒3 小时前
被Java的final坑惨了,这些细节你可能也忽略了
前端·人工智能·后端
kyriewen3 小时前
我带着DeepSeek Harness跑了一周真实需求——这份避坑速查表请收好
前端·ai编程·deepseek
计算机魔术师4 小时前
OpenAI不单独发o3了,Altman说GPT-5才是终局
前端
一座古城4 小时前
Claude Code 架构源码解析:AI 应用开发的范式跃迁
前端·后端
K哥爬虫4 小时前
【JS 逆向百例】Vaptcha V4 手势验证码逆向分析
前端·后端
用户921080262864 小时前
复盘 AI Coding 工作台的流式链路:从 Sender 输入到 SSE 分流,再到 BubbleList 和右侧预览
前端
了不起的小明4 小时前
SwiftMesh:本地 3D 模型查看器,加密交付 + 转盘录屏一站式搞定,开源免费
前端
默_笙4 小时前
👍 我的代码被 ESLint 抓包了:单引号、var、没分号——全被当场点名
前端·javascript