JS的函數(shù)定義方式以及對(duì)聲明的提前

前言

由于javascript中的函數(shù)定義方式比較特殊拄丰,并且每種的特點(diǎn)都不相同转唉,所以本文介紹一下JS幾種函數(shù)定義方式和各自的優(yōu)缺點(diǎn)劝堪,并且對(duì)JS中的函數(shù)聲明和變量聲明的hoist(提前)進(jìn)行簡(jiǎn)略說(shuō)明贬墩。

函數(shù)定義方式

函數(shù)生命式

這是js中比較常用的方式:

function funcname(a,b){
  //處理代碼
}

當(dāng)該函數(shù)被調(diào)用呀闻,函數(shù)體才會(huì)被得到執(zhí)行精肃。

function構(gòu)造函數(shù)方式

var funcname = new Function ('x', 'y', 'alert(x+y)');

該定義方式中前面兩個(gè)是參數(shù)秤涩,參數(shù)可以是任意多個(gè)字符串;第三個(gè)是函數(shù)體司抱,可以包含任何 JavaScript 語(yǔ)句筐眷,語(yǔ)句之間用分號(hào)隔開(kāi)。如果沒(méi)有參數(shù)习柠,傳一個(gè)函數(shù)體即可匀谣。由于傳遞給 Function () 函數(shù)中,沒(méi)有一個(gè)字符串是用來(lái)聲明函數(shù)名的资溃,所以它是一個(gè)匿名函數(shù)武翎。

函數(shù)直接量

var funcname = function(a,b){
  //處理代碼
}

區(qū)別

三種方式的區(qū)別,可以從作用域溶锭、效率以及加載順序來(lái)區(qū)分宝恶。首先,從作用域上來(lái)說(shuō)趴捅,函數(shù)聲明式和函數(shù)直接量使用的是局部變量垫毙,而 Function()構(gòu)造函數(shù)卻是全局變量:

var y = 'global';
function a(){
  var y = 'local a';
  return y;
}
alert(a());//顯示'local a'
var b = function(){
  var y = 'local b';
return y;
}
alert(b()) //顯示'local b'
function c(){
  var y = 'local c';
  return new Function('return y');
}
alert(c()());//顯示'global',因?yàn)镕unction()返回的是全局變量y拱绑,而不是函數(shù)體內(nèi)的局部變量综芥。

再看效率,F(xiàn)unction()構(gòu)造函數(shù)的效率要低于其他兩種方式猎拨,尤其是在循環(huán)體中毫痕,因?yàn)闃?gòu)造函數(shù)每執(zhí)行一次都要重新編譯,并且生成新的函數(shù)對(duì)象迟几。

最后是加載順序消请,function 方式(即函數(shù)聲明式)是在 JavaScript 編譯的時(shí)候就加載到作用域中,而其他兩種方式則是在代碼執(zhí)行的時(shí)候加載,如果在定義之前調(diào)用它类腮,則會(huì)返回 undefined臊泰。

函數(shù)聲明和變量聲明的提前

從上面對(duì)三種定義方式的比較來(lái)看,只有函數(shù)聲明方式定義的函數(shù)會(huì)在JS編譯的時(shí)候就加載到作用域中蚜枢,由此想到了JS中對(duì)聲明的提前

變量聲明提前:

(function() {
  console.log(a);//undefined
  var a = "Now it's defined!";
  console.log(a);//"Now it's defined!"
})();

在未對(duì)a進(jìn)行定義和聲明的時(shí)候輸出a卻提示undefined但沒(méi)有報(bào)錯(cuò)缸逃,這其實(shí)是 JavaScript 解析器搞的鬼针饥,解析器將當(dāng)前作用域內(nèi)聲明的所有變量和函數(shù)都會(huì)放到作用域的開(kāi)始處,但是需频,只有變量的聲明被提前到作用域的開(kāi)始處了丁眼,而賦值操作被保留在原處。

由于 JavaScript 具有這樣的“怪癖”昭殉,所以你會(huì)看到很多編碼指南建議大家將變量聲明放在作用域的最上方苞七,這樣就能時(shí)刻提醒自己注意了。

函數(shù)聲明提前:

第一種情況:

isItHoisted();//"Yes!"
function isItHoisted() {  
    console.log("Yes!");
}

如上所示挪丢,JavaScript 解釋器允許你在函數(shù)聲明之前使用蹂风,也就是說(shuō),函數(shù)聲明并不僅僅是函數(shù)名“被提前”了乾蓬,整個(gè)函數(shù)的定義也“被提前”了惠啄!所以上述代碼能夠正確執(zhí)行。

第二種情況:

funca();//"Definition hoisted!"
funcb();//拋出錯(cuò)誤:undefined is not a function
 
function funca() {  
    console.log("Definition hoisted!");
}
var funcb = function () {  
    console.log("Definition not hoisted!");
};

我們做了一個(gè)對(duì)比任内,funca函數(shù)被妥妥的執(zhí)行了撵渡,符合第一種類型;funcb函數(shù) 變量“被提前”了死嗦,但是他的賦值(也就是函數(shù))并沒(méi)有被提前趋距,從這一點(diǎn)上來(lái)說(shuō),和前面我們所講的變量“被提前”是完全一致的越走,并且棚品,由于“被提前”的變量的默認(rèn)值是 undefined 靠欢,所以報(bào)的錯(cuò)誤屬于“類型不匹配”廊敌,因?yàn)?undefined 不是函數(shù),當(dāng)然不能被調(diào)用门怪。

總結(jié)

通過(guò)上面的講解可以總結(jié)如下:

  • 變量的聲明被提前到作用域頂部骡澈,賦值保留在原地
  • 函數(shù)聲明方式定義函數(shù)整個(gè)“被提前”
  • 函數(shù)直接量定義函數(shù)的方式只有變量“被提前”了,函數(shù)沒(méi)有“被提前”

正好和前面所說(shuō)的函數(shù)定義的三種不同方式的區(qū)別是吻合的掷空。

所以提醒大家:作為最佳實(shí)踐肋殴,變量聲明一定要放在作用域/函數(shù)的最上方(JavaScript 只有函數(shù)作用域!)坦弟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末护锤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酿傍,更是在濱河造成了極大的恐慌烙懦,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赤炒,死亡現(xiàn)場(chǎng)離奇詭異氯析,居然都是意外死亡亏较,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門掩缓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雪情,“玉大人,你說(shuō)我怎么就攤上這事你辣⊙餐ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵绢记,是天一觀的道長(zhǎng)扁达。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蠢熄,這世上最難降的妖魔是什么跪解? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮签孔,結(jié)果婚禮上叉讥,老公的妹妹穿的比我還像新娘。我一直安慰自己饥追,他們只是感情好图仓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著但绕,像睡著了一般救崔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捏顺,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天六孵,我揣著相機(jī)與錄音,去河邊找鬼幅骄。 笑死劫窒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拆座。 我是一名探鬼主播主巍,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挪凑!你這毒婦竟也來(lái)了孕索?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤躏碳,失蹤者是張志新(化名)和其女友劉穎搞旭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡选脊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年杭抠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恳啥。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡偏灿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钝的,到底是詐尸還是另有隱情翁垂,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布硝桩,位于F島的核電站沿猜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碗脊。R本人自食惡果不足惜啼肩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衙伶。 院中可真熱鬧祈坠,春花似錦、人聲如沸矢劲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)芬沉。三九已至躺同,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丸逸,已是汗流浹背蹋艺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椭员,地道東北人车海。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓笛园,卻偏偏與公主長(zhǎng)得像隘击,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子研铆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容