所謂立即執(zhí)行函數(shù)就是聲明一個(gè)匿名函數(shù)幔托,立即執(zhí)行它
一般有三種寫(xiě)法:
(function(){})();
(function(){}());
!function(){}();
首先我們需要搞清楚函數(shù)表達(dá)式和函數(shù)聲明區(qū)別,ECMAScript規(guī)范中定義的相當(dāng)模糊:
函數(shù)聲明必須帶有標(biāo)示符(Identifier)(就是大家常說(shuō)的函數(shù)名稱),而函數(shù)表達(dá)式則可以省略這個(gè)標(biāo)示符:
函數(shù)聲明:
function 函數(shù)名稱 (參數(shù):可選){ 函數(shù)體 }
函數(shù)表達(dá)式:
function 函數(shù)名稱(可選)(參數(shù):可選){ 函數(shù)體 }
其實(shí)我們常用的區(qū)分方式是根據(jù)上下文,如果function fn(){}作為右值出現(xiàn)(賦值表達(dá)式右邊)那么就是表達(dá)式闺魏,否則就是函數(shù)聲明。有幾種看起來(lái)不常規(guī)的方式需要我們注意
new function fn(){}; //表達(dá)式俯画,因?yàn)樵趎ew 表達(dá)式中
(function(){}());//表達(dá)式析桥,在分組運(yùn)算符中
這樣我們就能理解第二種寫(xiě)法了,就是利用分組運(yùn)算符改變了語(yǔ)法樹(shù)艰垂。同樣第三種寫(xiě)法其實(shí)是利用了一元運(yùn)算符后面跟表達(dá)式的原理泡仗,我們也可以寫(xiě)成
+function(){}()
-function(){}()
~function(){}()
知道了這些看個(gè)傳入?yún)?shù)調(diào)用的立即執(zhí)行函數(shù)
(function f(f){
return typeof f();
})(function(){return 1;});// "number"
立即執(zhí)行函數(shù)不再是以空括號(hào)()來(lái)調(diào)用了,同時(shí)傳入了一個(gè)function作為參數(shù)傳入調(diào)用材泄。
當(dāng)函數(shù)執(zhí)行有命名沖突的時(shí)候沮焕,函數(shù)依次填入 變量=》函數(shù)=》參數(shù),所以最后被填入的參數(shù)f會(huì)覆蓋函數(shù)定義f拉宗,typeof f()是對(duì)參數(shù)的調(diào)用峦树,參數(shù)是立即執(zhí)行函數(shù)傳入的function參數(shù)辣辫,返回?cái)?shù)字1,typeof 1是 "number"魁巩。
表達(dá)式返回值
函數(shù)定義表達(dá)式返回的是函數(shù)對(duì)象本身急灭,我們?cè)谡{(diào)用alert或者console.log的時(shí)候會(huì)調(diào)用其toString方法
console.log(function(){alert('a');}) //function (){alert('a');}
函數(shù)調(diào)用表達(dá)式自然是返回函數(shù)的return結(jié)果,但在JavaScript中并不是所有的函數(shù)都有return語(yǔ)句谷遂,對(duì)于沒(méi)有return語(yǔ)句的function葬馋,其調(diào)用表達(dá)式返回undefined,對(duì)于只寫(xiě)個(gè)return的坑爹做法同樣也是返回undefined
(function(){})(); //undefined
(function(){return;})();//undefined
對(duì)象創(chuàng)建表達(dá)式本來(lái)也應(yīng)該很簡(jiǎn)單肾扰,返回new的對(duì)象就可以了
typeof new Date(); //"object"
當(dāng)使用function的構(gòu)造函數(shù)創(chuàng)建對(duì)象(new XXX)的時(shí)候畴嘶,如果函數(shù)return基本類型或者沒(méi)有return(其實(shí)就是return undefined)的時(shí)候, new 返回的是對(duì)象的實(shí)例集晚;如果 函數(shù)return的是一個(gè)對(duì)象窗悯,那么new 將返回這個(gè)對(duì)象而不是函數(shù)實(shí)例。