下面小編就為大家?guī)?lái)一篇淺析函數(shù)聲明和函數(shù)表達(dá)式——函數(shù)聲明的聲明提前。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。
前兩天班級(jí)聚會(huì),除了吃喝玩樂(lè)就是睡覺(jué)扯淡,甚是喜悅,真是獨(dú)樂(lè)樂(lè)不如眾樂(lè)樂(lè)啊。
PS:畢業(yè)的或即將畢業(yè)的有時(shí)間能聚就聚吧,畢了業(yè)以后屬于自己的時(shí)間能聚到一塊兒可就少太多了。
現(xiàn)在有點(diǎn)時(shí)間來(lái)看點(diǎn)東西總結(jié)些東西了,又因?yàn)榍岸螘r(shí)間片片斷斷地看了看JavaScript的函數(shù)部分,所以抽時(shí)間總結(jié)下函數(shù)的相關(guān)部分,當(dāng)然,里面有些部分都是自己的理解,如果有理解的不對(duì)的地方還請(qǐng)小伙伴們不吝指出。
這一節(jié)我結(jié)合自己的理解和小伙伴們聊一下函數(shù)聲明的聲明提前。
注:有的地方也叫函數(shù)聲明提升。翻譯的不一樣,意思一樣,大家理解就行。理解萬(wàn)歲!
在聊函數(shù)聲明的聲明提前之前,有必要介紹下函數(shù)定義的幾種方法,大部分小伙伴們應(yīng)該都不陌生。了解的或者不想了解的就痛快地一滾輪滾下去吧,不熟悉的或者想再熟悉一下的就放慢腳步起步走。
定義函數(shù)的方法
定義函數(shù)的方法主要有三種:
1.函數(shù)聲明(Function Declaration)
2.函數(shù)表達(dá)式Function Expression)
3.new Function構(gòu)造函數(shù)
其中,經(jīng)常使用的是函數(shù)聲明和函數(shù)表達(dá)式的函數(shù)定義方法,這兩種方法有著很微妙的區(qū)別和聯(lián)系,而且這兩種方法的使用也容易混淆,所以這篇文章主要總結(jié)下這兩種函數(shù)定義方法的相關(guān)知識(shí)點(diǎn),當(dāng)然本文的主題依然是關(guān)于函數(shù)提前的。
函數(shù)聲明的典型格式:
function functionName(arg1, arg2, ...){
<!-- function body -->
}
函數(shù)表達(dá)式
•函數(shù)表達(dá)式的典型格式:
var variable=function(arg1, arg2, ...){
<!-- function body -->
}
包含名稱(chēng)(括弧,函數(shù)名)的函數(shù)表達(dá)式:
var variable=function functionName(arg1, arg2, ...){
<!-- function body -->
}
像上面的帶有名稱(chēng)的函數(shù)表達(dá)式可以用來(lái)遞歸:
var variable=function functionName(x){
if(x<=1)
return 1;
else
return x*functionName(x);
}
聲明提前
var聲明提前
小伙伴們應(yīng)該都聽(tīng)說(shuō)過(guò)聲明提前的說(shuō)法,我想在此再次重申一遍,因?yàn)槁暶魈崆笆呛瘮?shù)聲明和函數(shù)表達(dá)式的一個(gè)重要區(qū)別,對(duì)于我們進(jìn)一步理解這兩種函數(shù)定義方法有著重要的意義。
但是再說(shuō)函數(shù)聲明提前之前呢,有必要說(shuō)一下var聲明提前。
先給出var聲明提前的結(jié)論:
變量在聲明它們的腳本或函數(shù)中都是有定義的,變量聲明語(yǔ)句會(huì)被提前到腳本或函數(shù)的頂部。但是,變量初始化的操作還是在原來(lái)var語(yǔ)句的位置執(zhí)行,在聲明語(yǔ)句之前變量的值是undefined。
上面的結(jié)論中可以總結(jié)出三個(gè)簡(jiǎn)單的點(diǎn):
1.變量聲明會(huì)提前到函數(shù)的頂部;
2.只是聲明被提前,初始化不提前,初始化還在原來(lái)初始化的位置進(jìn)行初始化;
3.在聲明之前變量的值是undefined。
還是來(lái)例子實(shí)在:
var handsome='handsome';
function handsomeToUgly(){
alert(handsome);
var handsome='ugly';
alert(handsome);
}
handsomeToUgly();
正確的輸出結(jié)果是:
先輸出undefined,然后輸出ugly。
錯(cuò)誤的輸出結(jié)果是:
先輸出handsome,然后輸出ugly。
這里正是變量聲明提前起到的作用。該handsome局部變量在整個(gè)函數(shù)體內(nèi)都是有定義的,在函數(shù)體內(nèi)的handsome變量壓住了,哦不對(duì),是覆蓋住了同名的handsome全局變量,因?yàn)樽兞柯暶魈崆?,即var handsome被提前至函數(shù)的頂部,就是這個(gè)樣子:
var handsome='handsome';
function handsomeToUgly(){
var handsome;
alert(handsome);
var handsome='ugly';
alert(handsome);
}
handsomeToUgly();
所以說(shuō)在alert(handsome)之前,已經(jīng)有了var handsome聲明,由上面提到的
在聲明之前變量的值是undefined
所以第一個(gè)輸出undefined。
又因?yàn)樯厦嫣岬降模?/P>
只是聲明被提前,初始化不提前,初始化還在原來(lái)初始化的位置進(jìn)行初始化
所以第二個(gè)輸出ugly。
函數(shù)聲明提前
接下倆我們結(jié)合var聲明提前開(kāi)始聊函數(shù)聲明的聲明提前。
函數(shù)聲明的聲明提前小伙伴們應(yīng)該很熟悉,舉個(gè)再熟悉不過(guò)的例子。
sayTruth();<!-- 函數(shù)聲明 -->
function sayTruth(){
alert('myvin is handsome.');
}
sayTruth();<!-- 函數(shù)表達(dá)式 -->
var sayTruth=function(){
alert('myvin is handsome.');
}
小伙伴們都知道,對(duì)于函數(shù)聲明的函數(shù)定義方法,即上面的第一種函數(shù)調(diào)用方法是正確的,可以輸出myvin is handsome.的真理,因?yàn)楹瘮?shù)調(diào)用語(yǔ)句可以放在函數(shù)聲明之后。而對(duì)于函數(shù)表達(dá)式的函數(shù)定義方法,即上面的第二種函數(shù)調(diào)用的方法是不能輸出myvin is handsome.的正確結(jié)果的。
結(jié)合上面的myvin is handsome.例子,函數(shù)聲明提前的結(jié)論似乎很好理解,不就是在使用函數(shù)聲明的函數(shù)定義方法的時(shí)候,函數(shù)調(diào)用可以放在任意位置嘛。對(duì)啊,你說(shuō)的很對(duì)啊,小伙伴,我都不知道怎么反駁你了。那就容我再扯幾句。
從小伙伴所說(shuō)的
不就是在使用函數(shù)聲明的函數(shù)定義方法的時(shí)候,函數(shù)調(diào)用可以放在任意位置嘛
可以引出一點(diǎn):
函數(shù)聲明提前的時(shí)候,函數(shù)聲明和函數(shù)體均提前了。
而且:
函數(shù)聲明是在預(yù)執(zhí)行期執(zhí)行的,就是說(shuō)函數(shù)聲明是在瀏覽器準(zhǔn)備執(zhí)行代碼的時(shí)候執(zhí)行的。因?yàn)楹瘮?shù)聲明在預(yù)執(zhí)行期被執(zhí)行,所以到了執(zhí)行期,函數(shù)聲明就不再執(zhí)行(人家都執(zhí)行過(guò)了自然就不再執(zhí)行了)。
上面是一點(diǎn)。
函數(shù)表達(dá)式為什么不能聲明提前
我們?cè)僬f(shuō)一點(diǎn):為什么函數(shù)表達(dá)式不能像函數(shù)聲明那樣進(jìn)行函數(shù)聲明提前呢?
辛虧我知道一點(diǎn)兒,否則真不知道我該怎么回答呢?
咳咳,按照我的理解給小伙伴們解釋一下下:
我們上面說(shuō)了var的聲明提前,注意我上面提過(guò)的:
只是聲明被提前,初始化不提前,初始化還在原來(lái)初始化的位置進(jìn)行初始化
Ok,我們把函數(shù)表達(dá)式擺在這看看:
var variable=function(arg1, arg2, ...){
<!-- function body -->
}
函數(shù)表達(dá)式就是把函數(shù)定義的方式寫(xiě)成表達(dá)式的方式(貌似是白說(shuō),但是這對(duì)于解釋和理解為毛函數(shù)表達(dá)式不能函數(shù)聲明提前具有良好的療效),就是把一個(gè)函數(shù)對(duì)象賦值給一個(gè)變量,所以我們把函數(shù)表達(dá)式寫(xiě)成這個(gè)樣子:
var varible=5看到這,也許小伙伴們會(huì)明白了,一個(gè)是把一個(gè)值賦值給一個(gè)變量,一個(gè)是把函數(shù)對(duì)象賦值給一個(gè)變量,所以對(duì)于函數(shù)表達(dá)式,變量賦值是不會(huì)提前的,即function(arg1, arg2, ...){<!-- function body -->}是不會(huì)提前的,所以函數(shù)定義并沒(méi)有被執(zhí)行,所以函數(shù)表達(dá)式不能像函數(shù)聲明那樣進(jìn)行函數(shù)聲明提前。
函數(shù)聲明提前的實(shí)例分析
還是那句話(huà),還是例子來(lái)的實(shí)在:
sayTruth();
if(1){
function sayTruth(){alert('myvin is handsome')};
}
else{
function sayTruth(){alert('myvin is ugly')};
}
在瀏覽器不拋出錯(cuò)誤的情況下(請(qǐng)自行測(cè)試相應(yīng)的瀏覽器是否有拋出錯(cuò)誤的情況,為啥我不測(cè)試?我能說(shuō)我懶么。。。),瀏覽器的輸出結(jié)果是輸出myvin is ugly(我不愿承認(rèn),但是事實(shí)就是這樣啊啊啊啊,難道道出了人丑就該多讀書(shū)??????)。
為什么呢?當(dāng)然是聲明提前了。因?yàn)楹瘮?shù)聲明提前,所以函數(shù)聲明會(huì)在代碼執(zhí)行前進(jìn)行解析,執(zhí)行順序是這樣的,先解析function sayTruth(){alert('myvin is handsome')},在解析function sayTruth(){alert('myvin is ugly')},覆蓋了前面的函數(shù)聲明,當(dāng)我們調(diào)用sayTruth()函數(shù)的時(shí)候,也就是到了代碼執(zhí)行期間,聲明會(huì)被忽略,所以自然會(huì)輸出myvin is ugly(好殘酷的現(xiàn)實(shí)。。。)。忘了的可以看上面說(shuō)過(guò)的:
函數(shù)聲明是在預(yù)執(zhí)行期執(zhí)行的,就是說(shuō)函數(shù)聲明是在瀏覽器準(zhǔn)備執(zhí)行代碼的時(shí)候執(zhí)行的。因?yàn)楹瘮?shù)聲明在預(yù)執(zhí)行期被執(zhí)行,所以到了執(zhí)行期,函數(shù)聲明就不再執(zhí)行了(人家都執(zhí)行過(guò)了自然就不再執(zhí)行了)。
小了個(gè)結(jié)
關(guān)于函數(shù)聲明的函數(shù)提前(提升)就聊到這里先,希望我的理解和扯淡能夠?qū)τ行枰男』锇橛兴鶐椭?/P>
當(dāng)然,實(shí)踐出真知。對(duì)事物的了解、認(rèn)知和運(yùn)用還是在于多看多用多總結(jié),記得有句名言,是講聲明和實(shí)踐的:“動(dòng)起來(lái),為新的聲明喝彩?!?。
以上這篇淺析函數(shù)聲明和函數(shù)表達(dá)式——函數(shù)聲明的聲明提前就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考