在条件语句中提升函数
Hoisting of functions inside conditionals
我了解 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 的输出如何?
在JavaScript中,变量、函数表达式和函数声明被提升到作用域的顶部。
函数声明定义一个命名函数变量而不需要变量赋值。
重要的是要知道函数声明的整个主体都提升了作用域。
例如
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".
然而,变量和函数表达式在没有指定值的情况下被提升。
例如
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
}
}
(忽略某些旧浏览器可能具有的轻微狡猾行为:)
在 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();
这是一个未指定的行为,不同的浏览器行为不同。
在chrome&firefox中,会输出foo is not a function
。
而在safari中,会输出b
.
这在现代 JS 浏览器中不再是正确的行为!现代浏览器将像这样编译和提升上述代码:
// hoisting (treat foo declarations as a normal variable declaration inside if statement)
var a;
var foo;
// now the assignment
foo(); // TypeError (foo = undefined)
a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
我了解 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 的输出如何?
在JavaScript中,变量、函数表达式和函数声明被提升到作用域的顶部。
函数声明定义一个命名函数变量而不需要变量赋值。
重要的是要知道函数声明的整个主体都提升了作用域。
例如
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".
然而,变量和函数表达式在没有指定值的情况下被提升。
例如
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
}
}
(忽略某些旧浏览器可能具有的轻微狡猾行为:)
在 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();
这是一个未指定的行为,不同的浏览器行为不同。
在chrome&firefox中,会输出foo is not a function
。
而在safari中,会输出b
.
这在现代 JS 浏览器中不再是正确的行为!现代浏览器将像这样编译和提升上述代码:
// hoisting (treat foo declarations as a normal variable declaration inside if statement)
var a;
var foo;
// now the assignment
foo(); // TypeError (foo = undefined)
a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}