一. 函數(shù)聲明
// 函數(shù)聲明
function funDeclaration(type){ return type==="Declaration"; }
二. 函數(shù)表達(dá)式
// 函數(shù)表達(dá)式
var funExpression = function(type){ return type==="Expression"; }
用函數(shù)聲明創(chuàng)建的函數(shù)funDeclaration可以在funDeclaration定義之前就進(jìn)行調(diào)用泛豪;而用函數(shù)表達(dá)式創(chuàng)建的funExpression函數(shù)不能在funExpression被賦值之前進(jìn)行調(diào)用歹叮。
為什么會(huì)這樣呢宅倒?!這就要理解Javascript Function兩種類型的區(qū)別:用函數(shù)聲明創(chuàng)建的函數(shù)可以在函數(shù)解析后調(diào)用(解析時(shí)進(jìn)行等邏輯處理)钦椭;而用函數(shù)表達(dá)式創(chuàng)建的函數(shù)是在運(yùn)行時(shí)進(jìn)行賦值填具,且要等到表達(dá)式賦值完成后才能調(diào)用猾昆。
這個(gè)區(qū)別看似微小肪凛,但在某些情況下確實(shí)是一個(gè)難以發(fā)現(xiàn)的陷阱态蒂。出現(xiàn)這個(gè)陷阱的本質(zhì)原因體現(xiàn)在這兩種類型在Javascript function hoisting(函數(shù)提升)和運(yùn)行時(shí)機(jī)(解析時(shí)/運(yùn)行時(shí))上的差異
三. 提升
誰(shuí)會(huì)被提升
變量聲明:使用var 杭措,let ,const關(guān)鍵字
函數(shù)聲明:使用function(){......}語(yǔ)法
類聲明:使用class關(guān)鍵字
- 函數(shù)聲明在函數(shù)作用域內(nèi)創(chuàng)建并初始化一個(gè)變量钾恢。默認(rèn)情況下手素,聲明但是未初始化的變量的值是undefined。
- javascript并沒(méi)有嚴(yán)格遵循這個(gè)順序瘩蚪,因此提供了更多的靈活性泉懦。比如:函數(shù)的使用可以在聲明之前。(目前就這個(gè))
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
}```
會(huì)輸出1二不是2疹瘦!這個(gè)代碼片段會(huì)被引擎理解為如下形式:
function foo(){
console.log(1);
}
foo();//1
foo = function(){
console.log(1);
}
foo();//1
注意:var foo盡管出現(xiàn)在 function foo()...的聲明之前崩哩,但它是重復(fù)的聲明(因此被忽略了),因?yàn)楹瘮?shù)聲明會(huì)被提升到普通變量之前言沐。
盡管**重復(fù)的var** 聲明會(huì)被忽略掉邓嘹,但出現(xiàn)在后面的函數(shù)聲明還是可以**覆蓋**前面的。
##四. 總結(jié)
無(wú)論作用域中的聲明出現(xiàn)在什么地方险胰,都將在代碼本身被執(zhí)行前首先進(jìn)行處理汹押。可以將這個(gè)過(guò)程形象地想象成所有的聲明(變量和函數(shù))都會(huì)被“移動(dòng)”到各自作用域的最頂端起便,這個(gè)過(guò)程被稱為提升鲸阻。
聲明本身會(huì)被提升,而包括函數(shù)表達(dá)式的賦值在內(nèi)的賦值操作并不會(huì)提升缨睡。要注意避免重復(fù)聲明鸟悴,特別是當(dāng)普通的var 聲明和函數(shù)聲明混合在一起的時(shí)候,否則會(huì)引起很多危險(xiǎn)的問(wèn)題奖年!
**參考至《你不知道的Javascript 上卷》**