全面了解JavaScript的函数声明与函数表达式、变量提升

函数的声明方式

在定义一个函数的时候通常有两种声明方式:

?
1
2
foo(){};   // 函数声明
var foo = function (){};  // 函数表达式

不同之处

1、函数表达式后面加括号可以直接执行
2、函数声明会提前预解析

预解析

让我们先看一个例子:

?
1
2
3
4
5
foo();     // 函数声明
foo_later();   // foo_later is not a function
 
function foo(){ console.log( '函数声明' ); }
var foo_later = function (){ console.log( '函数表达式' ); }

可以看到,函数声明foo被预解析了,它可以在其自身代码之前执行;而函数表达式foo_later则不能。要解决这个问题,我们先要弄清楚JavaScript解析器的工作机制。

变量提升(hoist)

JavaScript解析器会在自身作用域内将变量和函数声明提前(hoist),也就是说,上面的例子其实被解析器理解解析成了以下形式:

?
1
2
3
4
5
6
7
8
function foo(){ console.log( '函数声明' ); }  // 函数声明全部被提前
var foo_later;   // 函数表达式(变量声明)仅将变量提前,赋值操作没有被提前
 
foo();      
foo_later();  
 
 
foo_later = function (){ console.log( '函数表达式' ); }

这样也就可以解释,为什么在函数表达式之前调用函数,会返回错误了,因为它还没有被赋值,只是一个未定义变量,当然无法被执行。

同样的,我们也可以试着猜测下面这段代码的输出结果:

?
1
2
3
4
5
console.log(declaredLater); 
 
var declaredLater = "Now it's defined!" ;
 
console.log(declaredLater);

该段代码可以被解析成一下形式:

 

?
1
2
3
4
5
6
7
var declaredLater;    
 
console.log(declaredLater);  // undefined
 
declaredLater = "Now it's defined!" ;
 
console.log(declaredLater);  // Now it's defined!

 变量声明被提到最前(所以不会报出变量不存在的错误),但赋值没有被提前,所以第一次的输出结果是undefined。

需要注意的是

由于函数声明会被预解析,所以不要使用此种方法来声明不同函数。尝试猜想下面例子的输出结果:

?
1
2
3
4
5
6
7
8
9
10
11
12
if ( true ){
  function aaa(){
   alert( '1' );
  }
}
else {
  function aaa(){
   alert( '2' );
  }
}
 
aaa();

与我们预想的不同,该段代码弹出的是“2”.这是因为两个函数声明在if语句被执行之前就被预解析了,所以if语句根本没有用,调用aaa()的时候直接执行了下面的函数。

总结

通过上面的讲解可以总结如下:

•变量的声明被提前到作用域顶部,赋值保留在原地

•函数声明整个“被提前”

•函数作为值赋给变量时只有变量“被提前”了,函数没有“被提前”

通过练习上面的实例自己多感受一下。另外,作为最佳实践:变量声明一定要放在作用域/函数的最上方(JavaScript 只有函数作用域!)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值