if语句中的函数语句和函数表达式

时间:2013-12-29 13:48:48

标签: javascript

以下代码段在Firefox和Chrome中显示不同输出的任何原因:

var sayHo;
console.log(typeof(sayHey));
console.log(typeof(sayHo));
if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };
    sayHo = function() {
        console.log("Ho, inside if");
    };
}
else {
    function sayHey() {
       console.log("Hey, inside else");
    };
    sayHo = function() {
       console.log("Ho, inside else");
    };
}
sayHey();
sayHo();

Chrome(v31)输出

  1. 功能
  2. 未定义
  3. 嘿,在其他地方
  4. Ho,in if if
  5. Firefox(第26栏)输出

    1. 未定义
    2. 未定义
    3. 嘿,内在如果
    4. Ho,in if if
    5. 我预计Chrome会提供相同的输出。在解析时,内部的函数声明将覆盖if中的函数声明。因为JavaScript会尝试提升函数声明,因此覆盖。

2 个答案:

答案 0 :(得分:2)

Firefox和Chrome使用不同的JavaScript引擎(分别是SpiderMonkey和V8)。 Chrome行为可以被视为“错误”或“易用性功能”。在V8中,if语句中的函数定义(而不是将匿名函数赋值给变量)在执行前执行。这是一个设计决定。

答案 1 :(得分:0)

这一切归结为hoisting差异:

函数声明和变量声明始终由JavaScript解释器隐藏在其包含范围的顶部(“悬挂”)。显然,功能参数和语言定义的名称已经存在。这意味着代码如下:

function foo() {
    bar();
    var x = 1;
}

实际上是这样解释的:

function foo() {
    var x;
    bar();
    x = 1;
}

考虑这个例子:

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();

此代码相当于:

  function test() {

        function bar() { // function declaration, given the name 'bar'
            alert("this will run!");
         }
        foo(); // TypeError "foo is not a function"
        bar(); // "this will run!"
        var foo = function () { // function expression assigned to local variable 'foo'
            alert("this won't run!");
        }

    }
    test();

看看函数声明发生了什么:它被悬挂。

Leet看看更简单的样本:http://jsbin.com/UKICENE/4/edit

console.log(typeof(sayHey));

if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };}

sayHey();

这将在chrome中产生function

但它会在FF中产生undefined

Hoeever - 通过setTimeout推迟计算将产生与chrome相同的结果:

console.log(typeof(sayHey));//undefined

setTimeout(function (){console.log(typeof(sayHey));},1000); //function

if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };}

sayHey();

所以,就像Šime所说,它推迟了评估。

如果你问我,我认为chrome正在做正确的事