首页 >web前端 >js教程 >JavaScript提升 - 移动和停留什么

JavaScript提升 - 移动和停留什么

DDD
DDD原创
2025-01-30 08:30:10328浏览

Javascript Hoisting - What Moves and What Stays

JavaScript的提升机制就像舞台剧的布景准备。在代码运行之前(在“创建阶段”),JavaScript会将所有声明提升到其作用域的顶部,就像舞台工作人员在幕布升起前将道具搬到指定位置一样。唯一的区别是,只有声明被提升,初始化并没有被提升。

根据ECMAScript规范,这种行为实际上是JavaScript在创建阶段创建所谓的“词法环境”的一部分。但让我们不要过于技术化,只需记住JavaScript会在运行代码之前对其进行“预扫描”。

var 提升

<code class="language-javascript">console.log(x); // 输出:undefined
var x = 5;
console.log(x); // 输出:5</code>

在这个例子中,var x声明被提升到作用域的顶部,但初始化x = 5没有被提升。这就是为什么第一个console.log(x)输出undefined而不是抛出错误。变量x存在,但它还没有被赋值。

letconst 的暂时性死区 (TDZ)

<code class="language-javascript">console.log(y); // 抛出ReferenceError: Cannot access 'y' before initialization
let y = 10;
console.log(y); // 输出:10</code>

在这个例子中,let y声明被提升,但是它在初始化行之前位于暂时性死区 (TDZ)。在初始化之前尝试访问y会导致ReferenceError。此行为与var不同,var在类似情况下只会返回undefined

这也包括使用letconst声明的任何内容,当然也包括函数。

暂时性死区 (TDZ)

说到暂时性死区,这是letconst声明在初始化之前存在的地方。与var在初始化之前访问时返回undefined不同,这些现代声明会抛出错误。ECMAScript规范将此行为称为“暂时性死区语义”,但我称之为“JavaScript让我们诚实”。

一个稍微难一点的例子

<code class="language-javascript">function setupEventHandler() {
  handleClick(); // 可运行!

  const config = {
    debug: true,
  };

  function handleClick() {
    if (config?.debug) {
      // 未定义!
      console.log("Debug mode");
    }
  }
}

setupEventHandler();</code>

看到这里发生了什么吗?函数声明handleClick被提升了,所以我们可以提前调用它。但是config对象呢?它仍然留在它所在的位置。这就是为什么在handleClick内部访问config会给我们undefined,我们试图在脚本准备好之前读取它。

类声明的陷阱

类提升的工作方式不太一样。

<code class="language-javascript">const dog = new Animal(); // 抛出错误!

class Animal {
  constructor() {
    this.type = "mammal";
  }
}</code>

虽然类被提升了,但在它们的定义被评估之前,它们仍然处于“暂时性死区”。这意味着在声明它们之前,你无法访问它们。


记住,声明被移动到顶部,但初始化保持不变。

以上是JavaScript提升 - 移动和停留什么的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn