JS函数在if语句中的奇怪行为,为什么?

时间:2012-03-27 01:27:59

标签: javascript jquery

为什么下面的代码会返回“明显的”“惊讶!”(最后“怎么来?”)。它应该返回“expected”,不是吗? 在第一个if中我们使用了匿名函数,在第二个中我们使用了'命名'函数。

var a = 5;
if (a == 5) {
    var b = function () {
        return "obvious";
    };
} else {
    var b = function () {
        return "never";
    };
}

if (a == 5) {
    function c() {
        return "expected";
    }
} else {
    function c() {
        return "surprise!";
    }
    function d() {
        return "how come?";
    }
}

alert(b());
alert(c());
alert(d());

所以这意味着function a(){} is NOT equal to var a = function (){}

那么,第二个问题,为什么JS需要这种奇特的行为?这有什么好处?

3 个答案:

答案 0 :(得分:7)

不,它不应该,因为函数定义语句的语义不是你显然认为它们的语义。

函数定义语句总是被提升到封闭函数(或范围)的顶部。如果有多个具有相同名称的函数定义语句,则最后一个获胜。这不是一个动态的执行时间。将函数定义语句置于条件代码块中应该在语法上被禁止,但它不是。只是不要这样做。

您当然可以使用函数 instantiation 表达式来创建分配给变量的函数对象。那会像你期望的那样奏效。

答案 1 :(得分:4)

所有变量声明和函数声明都被提升到作用域的顶部,在本例中是脚本的顶部。这意味着代码被解释为是,

var a,b;
function c() { 
    return "expected"; 
} 
function c() { 
    return "surprise!"; 
} 
function d() { 
    return "how come?"; 
} 

a = 5; 
if (a == 5) { 
    b = function () { 
        return "obvious"; 
    }; 
} else { 
    b = function () { 
        return "never"; 
    }; 
} 

if (a == 5) { 
} 
else { 
} 

alert(b()); 
alert(c()); 
alert(d()); 

请注意,最后一个if语句为空,因为它们包含的所有函数声明都被提升。函数c的第二个声明掩盖了第一个。

我建议您避免在块语句中使用funciton声明语法。它是技术上不合法的JavaScript,但每个浏览器都支持它,即使它引起了你所注意到的混乱。

  

function a(){}不等于var a = function(){}。

正确。情况从未如此。

  

那么,第二个问题,为什么JS需要这种奇特的行为?这有什么好处?

JavaScript提升函数声明,以允许稍后在脚本中声明的函数由脚本中较早的函数使用。这使代码组织更加灵活。

答案 2 :(得分:1)

@Pointy是正确的。在计算第一个if语句之前,正在声明函数c()和d()。这就是为什么当你打电话给警报时,他们会做他们做的事情。