爱奇艺前端面试题有个题目如下:
a();
function a(){
console.log('a');
}
b();
var b = function(){
console.log('b');
}
那么函数的执行结果是?
熟悉函数变量提升的同学很容易就想到答案是:a undefined。
不熟悉的童鞋们可以接着往下看~
JS关于函数的声明,有一个很重要的特征就是函数的变量提升。意思是在执行代码之前会先读取函数的声明。这就意味着可以把函数声明放在调用它的语句后面。
sayHi();
function sayHi(){
alert('hi');
}
这个例子不会抛出错误,因为在代码执行前会被先去函数声明。
第二种创建函数的方式是使用函数表达式。函数表达式有几种不同的语法形式。下面是最常见的一种形式。
var functionName = function(arg0,arg1){
//函数体
};
这种形式看起来好像是常规的变量赋值语句,即创建一个函数并将它赋值给变量functionName。这种情况下创建的函数叫做匿名函数,因为function关键字后面没有标识符。匿名函数的name属性是空字符串。(匿名函数有时候也叫拉姆达函数)
函数表达式和其他表达式一样,在使用前必须先赋值。以下代码会导致错误:
sayHi();
var sayHi = function(){
alert('hi');
}
这也就是上面那道题输出结果的原因。
另外,执行以下代码的结果可能会让人意想不到。
//不要这样做!
if(condition){
function sayHi(){}
}
else{
function sayHi(){}
}
表面上看,以上代码在condition为true时,使用一个sayHi定义,否则使用另一个。实际上,这在ECMScript中属于无效的语法,JavaScript引擎会尝试修正错误,将其转化为合理的状态。但问题是浏览器尝试修正错误的做法并不一致。大多数浏览器会返回第二个声明,忽略condition;FIrefox会在condition为true时返回第一个声明。因此这种使用方式很危险,不应该出现在我们的代码中。
这种形式,JS引擎在预编译的过程中会注册方法到window对象下,就是window.sayHi。而不会顾及if else条件,导致重复的sayHi方法被注册,在这种情况下是无效语法。
不过,如果是使用函数表达式,那就没什么问题了。
//可以这样做
var sayHi;
if(condition){
sayHi = function(){
....
}
}
else{
sayHi = function(){
....
}
}
这个例子不会有什么意外,不同的函数会根据condition被赋值给sayHi。