JavaScript提升:它是什么以及为何实施
#javascript #hoisting

吊装是JavaScript中的一个关键概念,如果您不知道它的工作原理,可能会导致代码中的意外行为。

javaScript提升是指解释器在执行代码之前将函数,变量或类声明移至其范围顶部的过程。 em>

提升变量

  1. 如果您在第一次使用后声明一个变量,则此变量声明被“吊起”到其范围的顶部。
  2. 如果将值分配给变量,则分配的顺序不变,并且不受吊装的影响。

请参阅以下简单示例。

function myFunction() {
  console.log(myHoistedVariable); // undefined for ES5 and below
  var myHoistedVariable= 1;
  console.log(myHoistedVariable); // 1
}
  1. 由于悬挂了myHoistedVariable的声明,因此第一个console.log将尝试打印出值(注意。实际结果会有所不同,具体取决于您是否使用var,let or let or const或const)

  2. console.log将在值1的分配中打印不确定,而与吊装并没有移动(注意。这是仅使用var的es5)。

上面的示例基本与以下代码相同:

function myFunction() {
  var myHoistedVariable
  console.log(myHoistedVariable); // undefined for ES5 and below or ReferenceError for ES6 `let` or `const`
  myHoistedVariable = 1;
  console.log(myHoistedVariable); // 1
}

注意。 es5vâes6
从技术上讲仍然发生在ES6上,但在实际效果中,您将无法使用它。

  • es5:如果您使用的是var,则吊装值将返回未定义。此行为称为MDN。
  • es6:对于Let and Const声明,也将其悬挂在其范围的顶部,但并未以未定义的价值初始化。

实际上,这意味着您不能在声明之前使用let或const变量,否则您将获得参考。这称为MDN的Type 3提升行为。

如果您声明具有“使用严格”的JavaScript文件;这将意味着使用VAR升起将抛出3型参考器。 (有关更多信息,请参见this article from Digital Ocean

提升功能

功能提升变得更加有趣:

  • 功能声明将其悬挂在其范围的顶部。这意味着您可以在声明函数之前调用功能。
myHoistedFunction();

function myHoistedFunction() {
    console.log("Hi I'm hoisted!");
}
  • 函数表达式不悬挂。这意味着,如果您使用const声明函数表达式或在此声明之前无法调用该函数。箭头功能也是这种情况,因为它们也是函数表达式。

为什么根本提升?

如果这一切似乎都非常随机且不必要,那么它也对我来说也是如此 - 尤其是吊装变量。

您为什么不只是强制每个人在其范围的顶部声明变量,功能和课程?即使这在ES6中得到了很大的纠正,并且作为常规规范的功能表达式(另一天的另一个热门话题)。

历史原因

进一步挖掘这一点,我从档案中找到了这推文:

因此,

@aravind030792 var升起是功能提升的意想不到的后果,没有块范围,JS作为1995年的冲刺工作。 es6'let'可能会有所帮助。

brendaneich(@brendaneich)October 15, 2014

这个article on Quora进一步解释了这一点。 ** tl; dr ** Brendan Eich在10天内实施JavaScript(又名Livescript)时,希望避免使用ML语言的劳动声明上的痛苦到底执行诸如LISP之类的函数声明。

布伦丹还跟进了以下推文,澄清了VAR吊装是无意的:

因此,

@aravind030792 var升起是功能提升的意想不到的后果,没有块范围,JS作为1995年的冲刺工作。 es6'let'可能会有所帮助。

brendaneich(@brendaneich)October 15, 2014

从这种情况下 - 该功能确实有意义。

口译表绩效原因

当JavaScript引擎编译代码时,它首先经过一个称为解析的过程,将代码分解为较小,更易于管理的部分。

通过将函数声明移动到执行前的范围顶部,解释器可以避免在调用函数时搜索声明的声明。相反,它可以直接从内存执行该函数,该函数可以更快,更高效。

总而言之,似乎有两个关键好处:

  1. 允许您在定义函数声明之前使用它们。这使您可以组织放置功能代码的位置,无论将其称为何处,只要它们在同一范围内。

  2. 提高解释器的性能。由于可变声明在编译过程中移至其范围的顶部,因此可能会减少JavaScript引擎解析代码所需的时间。

关于与主题相关的提升/阅读材料的一些重要资源: