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

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

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 小时前
JavaScript 异步编程核心:从同步阻塞到 Promise 事件循环
javascript·promise
渣波1 小时前
前端开发主页面小技巧
前端·javascript
小林ixn1 小时前
前端必知:JS同步异步与Promise,终于有人讲明白了!
javascript·面试
柯克七七1 小时前
我用3个周末重构了公司的前端项目,老板没发现,但同事都来找我要代码了
前端
bonechips2 小时前
JS:同步与异步,从单线程到 Promise 的编程之路
前端·javascript
如果超人不会飞2 小时前
TinyVue Pager分页组件使用指南
前端·vue.js
看谷秀2 小时前
Git笔记
前端
Aolith2 小时前
从 Pinia 到 Zustand:我在 React 里复刻了一套用户状态管理
前端·react.js·typescript
先吃饱再说2 小时前
为什么 `setTimeout` 会“插队”?JS 事件循环与 Promise 通关笔记
前端·javascript·promise