什么是ES6中的暂时死区(Temporal Dead Zone)
介绍: 在开始之前,先思考一下这三个词的含义。暂时指的是临时的,非永久的;死区意味着无法使用或处于无生命状态;区域表示一个区域,但在这里我们是在编程中,所以这个区域与内存相关,或者区域可以被视为时间段或阶段。因此,合并这些术语说明某个实体暂时处于无生命或非活动状态,无法用于任何工作。为了更容易理解这个主题,你应该了解javascript中的let和const关键字。
为什么存在暂时死区?
这个问题可能会引起疑问,早期的javascript中它们并不存在,为什么我们需要它们?为什么ECMAScript在新更新中引入了这个额外的东西?实际上,在分配值之前访问变量是一件坏事。好吧,让我们假设javascript在内存中给变量分配了一些空间,只是因为你可能要在那里存储一些数据,那么为什么要在实际存入数据之前提取呢?大多数编程语言对于这种场景有不同的配置,例如C++在初始化之前存储垃圾数据,Python变量在初始化之前甚至不会被创建,Java存储默认值。
所以javascript有undefined,但由于内存分配阶段的变量提升,在线程执行阶段我们可以访问它们,因此,值显示为undefined。后来,当let和const被引入时,它们对于访问有一些限制,只是为了帮助javascript开发人员编写良好的代码和简化调试,所以新的暂时死区概念出现了,它帮助我们捕获错误,因为在提供数据之前访问某些数据是错误的。这是一个语言结构,可以帮助我们避免很多意外错误。
现在让我们通过不同的示例来理解。
示例1: 在这个示例中,我们简单地使用javascript代码片段,并使用var关键字来查看内存分配的过程。
index.js
<script>
console.log(x);
var x = 6;
console.log(x);
</script>
输出:

解释:
- 首先创建全局执行上下文。
- 然后开始内存分配阶段,此期间,变量x在内存中分配了一个位置,javascript将undefined放在那里。
- 然后开始线程执行阶段,此期间console.log(x)语句执行并打印存储在x中的值,即undefined。
- 在下一行中,x被赋值为6,x的undefined值被6替换。
- 再次在下一个console.log(x)中,x被打印为6。
示例2: 现在让我们使用let或const关键字来测试相同的代码片段。
index.js
<script>
console.log(x);
console.log(z);
var x = 6;
let z = 6;
console.log(x);
console.log(z);
</script>
输出:

说明:
- 首先会创建全局执行上下文。
- 然后开始内存分配阶段,在此阶段,变量x在内存中找到一个位置,并且javascript将undefined放在那里。
- 然后变量z在内存的另一个位置获得空间,和变量x一样,undefined将被赋予值。
- 然后开始线程执行阶段,此时console.log(x)语句执行并打印变量x的值,即undefined。
- 在下一行中,有console.log(z),javascript会抛出ReferenceError,并且程序会在此处停止。
变量的作用域: 现在让我们看一下这些变量存储在何处的作用域,注意var x是undefined并存储在全局对象中,而let z也是undefined但存储在名为Script的另一个位置,这意味着它们并不相同,javascript引擎要在它们的访问期间区分一些东西。在初始化let和const变量之前,它们无法访问,从声明let或const变量的执行块开始到该变量被初始化的这个过程被称为变量的暂时性死区。在此期间,如果任何人尝试访问这些变量,javascript将始终抛出引用错误。

示例 3: 在这个示例中,我们将看到处于暂时死区的变量。
index.js
<script>
console.log("Program Started and Variable z is in Temporal Dead Zone");
console.log("Variable z is in Temporal Dead Zone");
console.log("Variable z is in Temporal Dead Zone");
console.log("Variable z is in Temporal Dead Zone");
console.log("Variable z is in Temporal Dead Zone");
let z = 6;
console.log("Now Variable z is not in Temporal Dead Zone");
console.log(z);
</script>
输出:

解释:
- 在全局执行上下文的内存分配阶段中, let z 将在脚本对象内存中获得空间。
- 在线程执行阶段,console.log()的第一行将被执行,z也将处于暂时的死区,其中的值为undefined。
- 从第2行到第5行,变量仍然处于暂时的死区。
- 但是一旦在第6行我们用15初始化变量z,它将不再处于暂时的死区。
- 还有一点,你可能会想,将undefined赋值给z会使变量再次进入暂时的死区,不,这只是在最初的时候。而且,将其赋值为undefined并不是一个好习惯,因为javascript对该关键字有特殊的含义,所以不要乱用,否则可能会遇到意外的错误。
避免最常见的引用/类型错误和其他由暂时的死区引起的错误的方法:
克服暂时死区错误的最有效方法是在作用域的顶部初始化变量,这样当我们的代码开始运行时,它先完成初始化部分,然后在使用这些变量,否则在JavaScript代码中可能会遇到很多意外错误。
让我们来看一个示例 –
main.js
<script>
var x = 6;
let z = 6;
console.log(x);
console.log(z);
console.log(x);
console.log(z);
</script>
输出:

极客教程