为什么下面的代码会返回“明显的”,“惊讶!”(最后“怎么来?”)。它应该返回“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需要这种奇特的行为?这有什么好处?
答案 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()。这就是为什么当你打电话给警报时,他们会做他们做的事情。