JavaScript中的变量提升与块级作用域

4
foo(); 

var a = true;
if (a) {
   function foo() { console.log( "a" ); }
}
else {
   function foo() { console.log( "b" ); }
}

我的期望输出是b,但当我在浏览器中运行时,出现了foo不是一个函数的错误提示。

2个回答

3

这段类似的代码在MDN有解释

函数可以被条件性声明,也就是说,函数语句可以嵌套在if语句中,但是结果在不同的实现中不一致,因此这种模式不应该在生产代码中使用。对于条件性创建函数,请改用函数表达式。

var hoisted = "foo" in this;
console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
if (false) {
  function foo(){ return 1; }
}

// In Chrome:
// 'foo' name is hoisted. typeof foo is undefined
//
// In Firefox:
// 'foo' name is hoisted. typeof foo is undefined
//
// In Edge:
// 'foo' name is not hoisted. typeof foo is undefined
//
// In Safari:
// 'foo' name is hoisted. typeof foo is function

如果条件为真,则结果完全相同。

var hoisted = "foo" in this;
console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
if (true) {
  function foo(){ return 1; }
}

// In Chrome:
// 'foo' name is hoisted. typeof foo is undefined
//
// In Firefox:
// 'foo' name is hoisted. typeof foo is undefined
//
// In Edge:
// 'foo' name is not hoisted. typeof foo is undefined
//
// In Safari:
// 'foo' name is hoisted. typeof foo is function

看起来你把代码片段从You-Dont-Know-JS书系中的某个部分拿了出来,作者试图在其中解释this问题:

通常出现在正常块内的函数声明会提升到封闭作用域而不是像此代码所示的条件语句。...

[...code...]

然而,值得注意的是,这种行为并不可靠,并且可能会在JavaScript的未来版本中更改,因此最好避免在块中声明函数。


但是,“你不懂JS”这本书也是预期的答案是“b” @Arup Rakshit - Lalit Singh Tanwar

-2
在变量提升中,只有变量声明,没有赋值。

除了函数声明,它们也会提升函数值。 - Bergi
是的,仅适用于命名函数,而不适用于匿名函数。 - Krishna Kamal

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