在条件内提升功能

时间:2016-02-07 06:46:30

标签: javascript if-statement hoisting

我理解如何在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 输出怎么样?

3 个答案:

答案 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或循环块中作用域。所以你不能以这种方式有条件地声明一个函数 (它可以用另一种方式完成;见下文)。如果在同一范围内声明多个具有相同名称的函数,则后一个函数将覆盖第一个函数。

所以你的代码会发生什么:

  1. 两个函数语句都被提升,但

  2. 它们都有相同的名称,所以第一个被第二个覆盖。

  3. 已创建变量a但尚未分配值。

  4. 执行foo()语句,记录“b”

  5. a分配了值true

  6. 执行if。条件是正确的,但是if和else分支实际上都没有做任何事情,因为它们不包含除了先前提升的函数声明之外的语句。

  7. 如果要有条件地创建函数,则必须声明变量,然后为其分配函数表达式。然后你不能在该任务之后调用该函数:

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

答案 2 :(得分:0)

这是未指定的行为,不同的浏览器的行为有所不同。

MDN explain

在Chrome和Firefox中,它将输出foo is not a function

在Safari中,它将输出b

another doc of MDN