关于函数声明与函数表达式的一些理解
通常我们定义函数会用下面两种写法:
1、函数声明
function test(){
//...
}
2、函数表达式
var test = function(){
//...
};
表面上看没什么区别,实际上解析器会在执行任何代码前先读取声明,而函数表达式要等到解析器执行到它所在的代码行才会真正被执行。下面举个例子:
var test = function() {
console.log(2)
};
function test() { //这个是函数声明,将会被提升
console.log(1);
}
test()
结果是输出2,这个代码片段会被js理解为如下形式:
var test;
function test() {
console.log(1);
}
test = function() {
console.log(2)
};
test()
所有的声明(包括变量和函数)都会被移到作用域的顶端,这个过程叫做提升。函数表达式var test = function(){...}
会被拆分成两部分,var test
和test=function(){...}
;var test
会被提升,而赋值或其他运行逻辑会留在原地。引用一下《你所不知道的JavaScript》的一段话:
当你看到var a = 2;时,可能会认为这是一个声明。但JavaScript实际上会将其看成两个声明:var a;和a = 2;。第一个定义声明是在编译阶段进行的。第二个赋值声明会被留在原地等待执行阶段。
函数声明会被提升,而函数表达式却不会被提升。
test() //函数执行写在函数声明之前是没问题的,因为函数声明会提升
function test() {
console.log(1);
}
test() //报错:Uncaught TypeError: test is not a function
var test = function() {
console.log(1);
};
函数声明的使用有个值得注意的情况,应当避免:
if(true){
function test(){
alert(1)
}
}else{
function test(){
alert(2)
}
}
test()
按照这个条件判断的逻辑,返回的结果应该会是1
,而按照前面介绍的声明提升说法,结果是2
,函数声明会在代码执行前进行解析,先后解析function test(){ alert(1)}
和function test(){ alert(2)}
,后面的会覆盖前面的,最后到了执行阶段调用test()
,结果是返回2
。其实不同浏览器在这个的表现上可能不一样,旧版本的Chrome和IE(只看了IE8)输出的结果是2
,而最新版本的Chrome输出的结果是1
。总之,应当避免在条件判断这样的语句下声明函数。
而表达式形式这个写法是可以的,输出的结果都是1
var test;
if(true){
test = function (){
alert(1)
};
}else{
test = function (){
alert(2)
};
}
test()
手机阅读请扫描下方二维码:
12345678
1
1
1
1
1
1
1
1
1
1
1
1
1
1
12345678
xdwexmgpiexhpjgmgbxt
12345678
12345678
12345678
12345678
12345678
12345678
12345678
12345678
1
1
555
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1