【问题标题】:Is variable initialization also hoisted in JavaScript变量初始化是否也在 JavaScript 中提升
【发布时间】:2020-01-19 20:24:08
【问题描述】:

JavaScript 提升让我感到困惑。变量初始化是否提升?我认为它被提升了,因为我们在声明和初始化变量之前访问了它

console.log(a);
var a = 4;
undefined
undefined

undefined 表明变量 a 在代码执行之前被声明这是因为提升。

如果我错了,请纠正我。

【问题讨论】:

  • 欢迎使用 Stack Overflow - 这是来自浏览器控制台吗?
  • 声明被吊起; assignment 出现在它写入函数的行上。而且,正如@Mikkel 所说的那样(我认为),这只在函数范围内很重要。
  • developer.mozilla.org/en-US/docs/Glossary/… MDN 永远是这些东西的首选,那里有解释。
  • 重复多次.. 一个 cookie 到有效的重复关闭链接。

标签: javascript hoisting


【解决方案1】:

TLDR

在 JavaScript 中,变量和函数声明都被提升。

初始化不是。


Hoisting 意味着 - 无论声明的词法位置如何 - 标识符从封闭代码区域(函数或块)的最开始就在语义上存在。

这意味着标识符(即变量名)在语义上出现在声明它们的代码行之前 - 如果只是为了保证同名标识符之间不会发生混淆。

请注意,在评估变量声明之前,开发人员可能无法访问提升的标识符(例如,如果使用let 声明)。 IE。函数或块开始执行后的一段时间。这一时期的正式名称是“时间死区”。

在 JavaScript 中,变量和函数声明都会被提升。

初始化不是。

对于使用var 声明的变量,其效果是可以将声明想象为位于封闭函数的最顶部,而不管词法(即在代码中)位置如何声明。

对于严格模式代码(functionfunction*letconstclass)中的所有其他内容,可以想象声明位于封闭 block(可能是也可能不是函数),无论其声明的词法位置如何。

非严格代码有一个单独的、更复杂的set of rules 用于包含在块中的函数语句。见also

对于使用var 声明的变量,变量本身(默认值为undefined)可用于从封闭执行上下文的顶部进行赋值和取消引用(读取其值)。

提升的var 声明会自动初始化为undefined

对于其他所有内容,运行时都知道封闭块顶部的标识符,但在执行流程移过词法声明点之前,它不能用于赋值或取消引用。 IE。时间死区已经过去了。

提升的function/function* 声明立即使用提升的函数初始化。

请注意,在 JavaScript 中,初始化执行上下文(堆栈帧)的算法最后处理函数声明,这意味着 function 声明似乎比 var 声明“更高”。

这意味着如果一个函数声明和一个具有相同标识符的var在同一个函数中声明,则标识符将与function(而不是@987654342 @) 在封闭函数执行开始时。

对于letconstclass,在控件移过变量的词法声明之前,不会初始化标识符。

这些letconstclass 声明类型是在语言生命后期(ES 2015)中添加的。

语言设计者选择这种新行为是为了使 JavaScript 更易于理解,并避免在引入词法点声明之前允许赋值和取消引用的细微错误。

出于这个原因,在 JavaScript 中曾经有一个最佳实践,即应在其封闭函数的最顶部声明​​所述变量。

所以在你的示例代码中:

1  console.log(a);
2  var a = 4;
   undefined
   undefined

在执行之前,当代码的执行上下文(或堆栈帧)被实例化时,a 被提升到封闭范围的顶部。

a 是使用 var 声明的,因此在第 1 行,允许在 console.log(a) 内取消引用 a,并且将自动初始化的 undefined 值打印到控制台。

在第 2 行,代码会将4 分配给a(但不会打印任何内容)。

如果在浏览器控制台中运行,最终语句返回的值将由浏览器自动打印。

在这种情况下,var a = 4; 的结果是undefined,因此第二个undefined 会打印到控制台。

【讨论】:

  • "在声明的词法位置之前尝试使用 [let, const or class] 标识符将引发 ReferenceError" - 不,实际上是 these are hoisted as well。它们只是没有初始化为undefined
【解决方案2】:

其工作方式是该变量在整个程序中都可以访问,请参见以下内容:

'a'是未定义的,因为它没有在程序中声明,

但是,当我声明 a 时,它现在可以在整个程序中访问。

如果我设置了 a 的值,它只发生在控制台日志之后,操作顺序仍然保持不变,唯一提升的就是声明。

哈哈,我忘记了最后一个的 'a' 周围的括号,不太清楚为什么 quokka 仍然有预期的输出,quokka 赢得了阅读我的想法哈哈

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 2022-12-03
    • 2011-10-12
    • 2015-10-24
    • 2012-01-16
    相关资源
    最近更新 更多