我理解如何在javascript中进行提升,函数在变量之前被提升,只有声明被提升。但当我遇到 if / else 条件时,如下所示:
foo(); // "b is the output"
var a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
现在条件为真,所以根据if块, a 应该是输出,但由于某种提升,我假设 b 是输出
那么 b 输出怎么样?
答案 0 :(得分:1)
在JavaScript中,变量,函数表达式和函数声明被提升到范围的顶部。
函数声明定义了一个命名函数变量,而不需要变量赋值。
重要的是要知道函数声明的整个主体在范围内被提升。
E.g。
function outerFunction() {
console.log(typeof functionDeclaration); // outputs "function"
function functionDeclaration() {
// ... function body
}
}
这是因为,因为提升代码运行如下:
function outerFunction() {
function functionDeclaration() {
// ... function body
}
console.log(typeof functionDeclaration); // outputs "function"
}
在您的情况下,foo
的最后一个函数声明被提升到范围的顶部,覆盖所有其他函数声明。因此,它记录“b”。
但是,变量和函数表达式在没有指定值的情况下会被提升。
E.g。
function outerFunction() {
console.log(functionExpression); // outputs "undefined"
var functionExpression = function () {
// ... function body
}
}
运行更像是这样,
function outerFunction() {
var functionExpression = undefined;
console.log(functionExpression); // outputs "undefined"
functionExpression = function () {
// ... function body
}
}
答案 1 :(得分:1)
(忽略某些旧浏览器可能具有的略微狡猾的行为:)
在Javascript中,函数语句在包含函数的范围内(或者如果没有包含函数则是全局的),它们不在if或else或循环块中作用域。所以你不能以这种方式有条件地声明一个函数 (它可以用另一种方式完成;见下文)。如果在同一范围内声明多个具有相同名称的函数,则后一个函数将覆盖第一个函数。
所以你的代码会发生什么:
两个函数语句都被提升,但
它们都有相同的名称,所以第一个被第二个覆盖。
已创建变量a
但尚未分配值。
执行foo()
语句,记录“b”
a
分配了值true
。
执行if。条件是正确的,但是if和else分支实际上都没有做任何事情,因为它们不包含除了先前提升的函数声明之外的语句。
如果要有条件地创建函数,则必须声明变量,然后为其分配函数表达式。然后你不能在该任务之后调用该函数:
var foo;
var a = true;
if(a)
foo = function() { console.log("a"); };
else
foo = function() { console.log("b"); };
foo();
答案 2 :(得分:0)
这是未指定的行为,不同的浏览器的行为有所不同。
在Chrome和Firefox中,它将输出foo is not a function
。
在Safari中,它将输出b
。