暂时性死区是否和闭包是相背的呢(自学用)

先说结论:两者不相背,甚至经常配合出现

1. 它们本质不同

  • 暂时性死区 (TDZ)
    是一个时间阶段 的限制:在 let/const 声明之前,变量不可访问。防止你在未初始化时就用它。
  • 闭包
    是一个空间关系的能力:函数能记住并访问它被创建时所在的作用域里的变量。让你在函数执行上下文销毁后,还能用那些变量。

2. 经典结合案例:用 TDZ 创造闭包陷阱

循环绑定事件是最经典的"闭包 + TDZ"交互场景。

如果 TDZ 和闭包相背,这段代码就该报错,但实际上它能运行(只是结果不符合预期):

js 复制代码
function badLoop() {
  // let i = 0; // 如果用 let,表现会完全不一样
  for (var i = 0; i < 3; i++) {
    setTimeout(function() {
      // 这是一个闭包:它访问了外部作用域的变量 i
      console.log(i);
    }, 0);
  }
}
badLoop(); // 输出 3, 3, 3

闭包视角setTimeout 回调记住了变量 i,而不是它的值。

TDZ 视角

  • var:没有 TDZ,i 被提升为函数级变量,循环结束后是 3,所有闭包共享同一个 i
  • let:有 TDZ,但每次迭代都有独立的词法作用域,i 在每次迭代的 TDZ 之后被初始化为不同的值。这恰好修正了闭包的问题。
js 复制代码
function goodLoop() {
  for (let i = 0; i < 3; i++) { // i 有块级作用域
    setTimeout(function() {
      console.log(i);
    }, 0);
  }
}
goodLoop(); // 输出 0, 1, 2

这里 TDZ 的存在确保了变量必须先声明后使用 ,而 let 的循环特性创造了三个独立的绑定 ,让闭包捕获到了不同的值。它们在这里是协作关系


3. 也可能互相"阻挡"

闭包让你能"看到"外部变量,TDZ 又让你暂时"不能摸"它,就会产生错误:

js 复制代码
function test() {
  // 这是一个闭包,它想访问 TDZ 里的变量
  const show = () => console.log(myName);

  show(); // ❌ ReferenceError: Cannot access 'myName' before initialization

  const myName = 'TDZ';
}
test();

这里,show 这个闭包想用 myName,但执行时它还在 TDZ 里,所以报错。这是TDZ 阻止了闭包在合法时机前访问变量 ,而不是它们相背。如果相背,闭包就不该能看见这个变量,但实际是看得见,不许动


总结

  • 闭包是空间概念:让你跨作用域访问变量。
  • TDZ 是时间概念:让你只能在变量初始化后访问它。

它们之间不存在根本矛盾,更像是:闭包锁定了变量引用,TDZ 则给这个引用加上了一个"时间锁",必须在正确的时间点才能使用。

相关推荐
shmily麻瓜小菜鸡26 分钟前
JavaScript / TypeScript 易踩坑知识点 —— 异步编程类
开发语言·javascript·typescript
tsumikistep1 小时前
【前端】Vue + Axios 跨域问题实战:7070 代理转发 8080 + 401 报错分析(黑马外卖)
前端·javascript·vue.js
lichenyang4531 小时前
鸿蒙首页从等高商品 Grid 到双列瀑布流:同一张图也能做出小红书式浏览节奏
前端
里欧跑得慢1 小时前
Flutter主题与样式详解
前端·css·flutter·web
计算机魔术师1 小时前
TPU推理性价比翻50%,NVIDIA的护城河要见底了?
前端
IT_陈寒2 小时前
Python的多线程就是个假把式,我算是体验到了
前端·人工智能·后端
OpenTiny社区2 小时前
【直播分享】GenUI SDK 技术公开课第二讲 | GenuiChat 核心配置深度解析
前端·github
计算机魔术师2 小时前
kernel.org 每天 600 万次请求,98% 不是人点的
前端
今日无bug2 小时前
从0到1手撕流式输出:Vue3 + Vite 实现 LLM 流式响应全解析
前端·vue.js·vite
光影少年3 小时前
react navite跨端项目的痛点、踩过哪些坑、怎么解决
前端·react native·react.js