JavaScript中使用提升的主要优势是什么?

6
几天前,我参加了一次面试,其中有一个问题是“什么是提升(Hoisting)?”我详细解释了提升的概念,然后面试官问我,“提升的主要优势是什么?”我无法回答。 那么在JavaScript中,提升的主要优势是什么?

1
我非常喜欢函数声明被提升到其作用域顶部的方式,因为这样你就不必担心使用和声明的顺序。 - Maheer Ali
@MaheerAli 是的,你可以把最抽象的代码放在脚本的顶部,这样做,想把它作为答案发布吗?(虽然除了函数声明之外,我想不出有什么有用的优势) - CertainPerformance
JavaScript为什么会提升变量? - adiga
提升的主要优点是能够提出面试问题。 - Epicurist
5
@ Epicurist ... 几乎是这样。hoisting 的主要优点在于能够关于它提出毫无意义和混乱的面试问题。 - Bart Hofland
显示剩余2条评论
5个回答

7

方便吗?

真的很方便。无论是对于代码的读者还是编写代码的人本身都是如此。这并不是因为变量提升,而是因为函数提升。通过这种方式,您可以将辅助函数放在代码底部,将显示业务逻辑的更抽象的函数放在顶部。

我喜欢quora上关于同一主题的这个回答https://www.quora.com/Why-does-JavaScript-hoist-variables

换句话说,JavaScript实现了函数声明的提升,以便程序员不必强制将最内层函数放在脚本块的顶部,将最外层(顶级)函数放在底部。这种顺序,在ML语言(如LISP)中是痛苦的,因为程序员更喜欢从上到下阅读代码,而不是从下到上。像C / C ++这样的语言通过使用头文件和独立声明来解决此问题,而JavaScript没有。此外,提升对于实现相互递归是必需的。


1
你专注于函数提升,那普通变量呢? - deceze
变量提升或多或少只是函数提升的副产品。 - yunzen
先有鸡还是先有蛋… - deceze
函数也是变量。你可以用var foo = function () { ... }代替function foo() { ... }。所以我认为函数提升和变量提升在技术上没有区别,只是一种概念上的区别。 - Bart Hofland

0

嗯,每件事都有其优点和缺点,但在这种情况下,缺点似乎超过了优点。

在我看来,提升使代码更难理解。但这只是我的观点。当我编写代码时,我希望我的绑定在我声明它们的代码点处声明。这样,如果我错误地在声明之前使用它们,我就会得到通知。而且我肯定不想意外地声明两次,这是完全有效但也很令人困惑的。

我希望编译器/解释器在我做一些愚蠢的事情时能帮助我。提升允许我做太多方便和/或愚蠢的事情,可能导致数小时的复杂调试会话。因此,自ES6以来,我主要使用letconst而不是var。如果可以避免提升,那就不要用它。;)

所以,对于“提升的(主要)优点是什么?”这个问题,我的答案是:“我真的不在乎。”

编辑:

好吧,也许我在这里有点太苛刻了。函数提升实际上可能是有用和方便的,可以提高代码的可读性。但在函数内部,我会尽量避免变量提升。


0

0
一个名称(变量名,函数名)的作用域限定在其块内。使用 var 时,作用域是函数体;使用 let/const 时,作用域是最近的封闭 {} 块。由于 Javascript 中可能存在嵌套作用域,必须明确变量属于哪个块。如果你在特定的 中的 任何位置 提到了 var foo/let foo,那么该块就被保留为此变量的作用域。
function () {
/**** scope of foo *****/
/*/
/*/ var foo;
/*/
/*/ function () {
/*/ /** scope of bar **/
/*/ /*/
/*/ /*/ var bar;
/*/ /*/
/*/ /******************/
/*/ }
/**********************/
}

如果变量作用域只从声明var ...的确切开始,那将会非常令人困惑;因此,函数的一半将有一个变量作用域,而另一半则有另一个。因此,如果在块中的任何地方存在var/let,那么该名称将被提升以涵盖整个块。


-2

提升在某些情况下非常有用。例如,我们正在创建一个大型项目。它有很多帮助方法,通过将它们放在另一个脚本中进行分离。如果使用函数声明来声明它们,我们就不必担心脚本的顺序。否则,我们可能会遇到问题。

另一个用途是当我们使用递归时。考虑一个使用递归打印数字的函数。

(function print(n){
  if(n === 0) return;
  console.log(n)
  print(n-1)
})(4);

现在,如果没有变量提升,代码可能会抛出“未定义打印”错误。

1
你的例子并没有展示变量提升。 - deceze
1
抱歉,n已经在您的递归函数的参数列表中定义,我认为没有涉及到提升。 - Epicurist
@deceze 你能详细说明一下吗? - Maheer Ali
实际上,print 函数递归调用自身的事实,即使没有提升也可以正常工作:const print = function (n) { if (n === 0) return; console.log(n); print(n - 1); }; 同样是完全有效的。递归函数只有在它们是相互递归时才可能成为问题,例如当函数 A 调用函数 B 并且函数 B 再次调用函数 A 时。如果没有提升,创建这样的函数将会很棘手。(首先,您需要使用 let 创建两个函数的占位符变量,然后为它们分配函数体。这不是很直观。) - Bart Hofland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接