在网上看到这样一段代码
var condition = true;
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
sayHi();
但结果却是yo!
为什么呢?
加个日志应该很明显,和if进的分支没有关系,和js加载方法是有关的,function这种方式定义方法的话,js是从上往下加载的,同方法名的话,后面的会覆盖前面的方法,还没运行的时候,第二个sayHi已经把第一个sayHi覆盖了
var condition = true;
alert("33"+condition);
if(condition){
alert(44);
function sayHi(){
alert(11);
alert("Hi!");
}
} else {
function sayHi(){
alert(22);
alert("Yo!");
}
}
sayHi();
换一种函数定义方法,结果就不同了
var condition = true;
alert("33"+condition);
var sayHi;
if(condition){
alert(44);
sayHi = function(){
alert(11);
alert("Hi!");
}
} else {
sayHi = function(){
alert(22);
alert("Yo!");
}
}
sayHi();
没猜错的话这段代码出自于:javascript高级程序设计
,因为我也看到这里了。下面摘自书上内容:
关于函数声明,它的一个重要特征就是函数声明提升(
function declaration hoisting
),意思是在执行代码之前会先读取函数声明。
表面上看,以上代码在condition
为true
时,使用一个sayHi()
的定义;否则就使用另一个定义。实际上,这在ECMAScript
中属于无效语法,javascript
引擎会尝试修正错误,将其转正为合理的状态。但问题是浏览器尝试修正错误的做法不一致。大多数浏览器会返回第二个声明,忽略condition;Firefox
会在condition
为true
时返回第一个声明。因此这种使用方式很危险,不应该出现在你的代码中。不过如果使用函数表达式,那就没有问题了。
var sayHi;
var condition = false;
if (condition) {
sayHi = function () {
alert('Hi');
};
} else {
sayHi = function () {
alert('Yo');
};
}
sayHi(); // 执行
纯手打,如果对题主有帮助,很高兴。
function sayHi(){} 这种是函数声明式写法,会声明提前,将它置于最接近的环境中(这里是全局执行环境了)。
而你两次都是同一个函数名,后一个会覆盖前一个。所以你得到的就是 Yo!
你的相当于这样:
function sayHi(){
alert("Hi!");
}
function sayHi(){
alert("Yo!");
}
var condition = true;
if(condition){
} else {
}
sayHi();
是函数被覆盖了