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

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

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 则给这个引用加上了一个"时间锁",必须在正确的时间点才能使用。

相关推荐
吃糖的小孩1 小时前
从只读页面到可控真实探针:我如何给 Owner Console 加手动诊断
前端
谷无姜1 小时前
为什么你的性能优化无效?可能是"木桶效应"在作祟
前端·性能优化
雾非雾1 小时前
《基于具身交互智能数字人技术:如何打造AI数字人宣讲平台"红厅智播”》
前端
Revolution611 小时前
一段 JavaScript 代码执行时,到底发生了什么
前端·javascript
智能起源1 小时前
关于元素层级过多,导致压祯的问题(使用winform或者WPF应用的webview组件嵌套网页时,动效卡顿问题)
前端
Old Uncle Tom2 小时前
银行用户画像 -- 金融目标与需求意图
前端·人工智能·金融
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
东方小月2 小时前
从0开发一个 Coding Agent(一):前言
前端·人工智能·typescript
恋猫de小郭2 小时前
Flutter 全新真 3D 实现,用 flutter_scene 能开发一个「我的世界」
android·前端·flutter