微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么不能在用 let 和 const 声明变量之前完成赋值?

如何解决为什么不能在用 let 和 const 声明变量之前完成赋值?

我在多个网站(如 w3schools)上读到,提升是“将所有声明移动到当前范围顶部的行为”。

对于 letconst,变量被提升但未初始化。

我理解为什么以下代码不起作用,因为 name 没有可供我们访问的价值。

console.log(name);
let name = "hi";

但是为什么我们不能在实际声明之前为 name 赋值,即使 name 已经声明(提升)?

name = "hi";
let name;
console.log(name);

上面的代码是不是和下面的一样,

let name;
name = "hi";
console.log(name);

解决方法

因为它们被明确设计为不允许这样做,因为这通常是编程错误。

letconst 提升了,但这只是提升了绑定的声明。 (松散地,“绑定”的意思是“变量”[或常量或参数......我们用来保存值的名称的东西]。)直到稍后,当 {{1} } 或 let 语句在代码的逐步执行中达到。您不能使用未初始化的绑定(以任何方式),这就是您收到错误的原因。

相比之下,使用 const 声明 初始化都被提升; var 绑定使用值 var 进行初始化。如果 undefined (var) 上有初始化值,稍后在代码的逐步执行中到达 var a = 42 语句时,该部分被视为简单赋值(var)。使用 a = 42let,这不仅仅是简单的赋值,而是绑定的初始化,允许使用。

下面是一个具体的例子,说明 const 如何提升声明而不是初始化,以及为什么它有助于防止编程错误:

let

在该代码中,似乎 let a = 1; function foo() { a = 2; // <=== Which `a` should be assigned to? console.log(a); // code // code // code // code // code // code // code // code let a = 3; console.log(a); } foo(); 顶部的分配应该分配给外部 foo,因为(据我们所知,自上而下阅读)没有其他 {{1 }} 在适用范围。但是有,因为 a 底部的 a 被提升了。由于内部 let 未初始化,因此您在执行分配时出错。

相比之下,foo 没有错误,但很容易混淆 a 被分配在 var 的顶部。


在评论中,您表示您仍然不理解声明绑定但未初始化的绑定意味着什么。我认为“初始化”¹ 的两个(略微)含义在这里让您感到困惑(当我进入这些东西时它们让我感到困惑),所以让我们稍微改变术语。

绑定有一个与它们相关联的标志,说明它们是否可以使用。让我们称其为 a 标志:foo 表示可以使用绑定,usable 表示不能使用。使用该术语,上述示例的处理方式如下:

  1. 创建脚本的执行上下文时:

    1. 为其中的所有顶级声明创建绑定:
      • usable = trueusable = false 部分创建了一个名为 let a 的绑定,其 let a = 1; 标志设置为 a(尚不能使用)。
      • 函数声明 (usable) 创建了一个名为 false 的绑定,其 function foo() { } 标志设置为 foo(可以使用),其值设置为 {{1 }}。
    2. 上下文中的函数声明是通过创建它们定义的函数并将它们分配给绑定来处理的。所以 usable 得到它的函数值。
  2. 在代码的分步执行中遇到true语句时,它会做两件事:将undefined标志设置为foo(可以使用)并将 let a = 1; 的值设置为 usable

  3. 当调用 true 并创建调用的执行上下文时,会创建顶级声明的绑定:

    1. 名为 a 的绑定由 1 创建,其 foo 标志设置为 a(尚不能使用)。
  4. 在代码的逐步执行中到达 let a = 3; 语句时,usable 解析为内部 false 绑定({{ 1}},由 a = 2; 声明),但该绑定的 a 标志是 a,因此尝试使用它会引发错误。

  5. 如果我们没有foo语句,所以没有抛出错误,那么当分步代码执行时到达 let a = 3; 语句,它会做两件事:将 usable 标志设置为 false(可以使用)并将 a = 2; 的值设置为 let a = 3; .

usable 更新了一些评论:

true

¹ “我认为“初始化”¹的两个(稍微)含义在这里让您感到困惑......”我所指的两个含义是:

  1. “初始化”绑定(使其可用,将 a 设置为 3),并单独
  2. “初始化”就像设置绑定的初始值一样。

它们是不同的东西。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。