【发布时间】:2021-09-13 13:12:13
【问题描述】:
所以是的,这是你实际上不想做的事情,你总是想避免为不同的函数使用相同的名称 + 你不想再使用 var 来声明变量,因为这会导致很多的问题,但我很好奇为什么会发生这种情况!
我们知道用关键字var声明的变量和函数声明在创建阶段被提升到它们的函数范围的顶部,让我们先看一个变量的例子:
function f(){
console.log(p) // undefined
if(true){
var p = true;
}
}
f()
由于我们在 if 块中声明了一个变量,并且由于 if 没有获得自己的执行上下文,所以我们得到了 undefined,我们声明的变量被提升到顶部,如下所示:
function f(){
// under the hood
var p = undefined;
console.log(p) // undefined
if(true){
p = true;
}
}
f()
一切都说得通了,现在我们用函数来举例吧!
function f(){
let num = 5;
if(num < 10){
function a(){
console.log('less than 10')
}
a()
} else if(num < 20){
function a(){
console.log('less than 20')
}
a()
} else {
function a(){
console.log('something else')
}
a()
}
}
f()
这会返回“小于 10”,但为什么呢?
我预计吊装会像这样发生:
function f(){
/* HOISTING
function a(){
console.log('something else')
}
// HOISTING COMPLETED
*/
let num = 5;
if(num < 10){
a()
} else if(num < 20){
a()
} else {
a()
}
}
f()
因为我们在每个 if-else 块 a 中都有同名的函数,所以无论我们将什么值放入 num 变量中,都应该使用最后一个!
我们知道如果我们有多个同名函数,则使用最后一个,因为这是最后一个被提升的函数,如本例所示:
function f(){
b() // false
function b(){
console.log(true);
}
function b(){
console.log(false);
}
}
f()
那么 if-else 是怎么回事?
for 循环也是如此。 For 循环没有自己的执行上下文,因此使用 var 关键字和函数声明声明的变量也应该提升到其主函数范围的顶部,不是吗?但是这段代码不起作用:
function f(){
ff();
for (let i=0; i<1; i++){
function ff(){
console.log(true);
}
}
}
f();
我希望 for 循环“ff”中的函数被提升到我们的主 f 函数的顶部,但它没有!
(再一次,我知道定义两个同名函数,或者在声明之前调用函数,使用 var 关键字等是一种糟糕的做法。这些都是你一直想避免的事情,但我正在深入研究并试图解决此类问题)
【问题讨论】:
-
这是因为提升发生在解析阶段而不是执行阶段 - 因此最后一个函数获胜
-
是的,不要使用块级函数,因为你会遇到各种可怕的边缘情况。
-
从 2015 年开始,忽略 web 兼容模式,函数声明是块范围的,就像
let和const。
标签: javascript function for-loop var hoisting