在上篇談到匿名函數(shù)和回調(diào)函數(shù)的基礎(chǔ)上,我們接著介紹javascript中的即時(shí)函數(shù),內(nèi)部函數(shù),返回函數(shù)的函數(shù),能重寫自身的函數(shù)等幾種常見的函數(shù)類型及使用方法。只需要大致了解匿名函數(shù)的概念,應(yīng)該就能看懂這些內(nèi)容
即時(shí)函數(shù)
首先,我們介紹第一個(gè)較為簡(jiǎn)單常用的即時(shí)函數(shù)
我們看到下面這一串代碼
(function () {
alert('boo');
}
) ();
粗看一下,這段代碼似乎很奇怪,其實(shí)仔細(xì)分析不難發(fā)現(xiàn)這就是定義了一個(gè)匿名函數(shù),并且立即就調(diào)用執(zhí)行了這個(gè)匿名函數(shù)。第一對(duì)括號(hào)中的是匿名函數(shù)的定義,隨后緊跟的一對(duì)括號(hào)是對(duì)匿名函數(shù)的調(diào)用。
下面這個(gè)例子在調(diào)用的時(shí)候,傳入了參數(shù),更好的說明了即時(shí)函數(shù)的用法。
(function (name) {
alert('hello ' + name + '!')
}) ('liu chi')
即時(shí)函數(shù)的使用形式一般有兩種:
第一種就是剛剛介紹的(定義function)()后面的()就是調(diào)用的。
第二種就是(function (調(diào)用))
兩種方法都是一樣的,看自己的習(xí)慣選取適合自己的使用即時(shí)函數(shù)的方法。
使用即時(shí)函數(shù)有什么好處呢?
顯然我們可以看到使用即時(shí)函數(shù)調(diào)用完之后,所有的東西都沒了銷毀了,全是一次性的,不會(huì)產(chǎn)生任何的全局變量占用空間等等。
但也有一個(gè)缺點(diǎn)就是即時(shí)函數(shù)是無法重復(fù)執(zhí)行的,這好像就失去了函數(shù)重復(fù)調(diào)用的意義。
所以,一般來說即時(shí)函數(shù)通常用來執(zhí)行一次性的操作或者異類初始化的任務(wù)。
內(nèi)部函數(shù)
從上一篇文章中,我們顯然知道,在javascript中,函數(shù)與其他類型的值在本質(zhì)上是一樣的,函數(shù)本身也是一種值。所以,我們自然就可以在一個(gè)函數(shù)內(nèi)部定義另外一個(gè)函數(shù),這樣的函數(shù)就叫做內(nèi)部函數(shù)。
看下面這段代碼:
function outer(param) {
function inner(theinput) {
return theinput * 2;
}
return 'the result is ' + inner(param);
}
我們?cè)賝uter函數(shù)內(nèi)部定義了一個(gè)內(nèi)部函數(shù)inner,并在里面調(diào)用inner函數(shù)。
outer(2);
inner(3);
上面這段代碼的執(zhí)行結(jié)果:
"the result is 4"
ReferenceError: inner is not defined
...on inner(theinput) { return theinput * 2; } return 'the result is ' + in...
我們知道內(nèi)部函數(shù)只能在定義它的函數(shù)內(nèi)部調(diào)用它,不能再外部調(diào)用它。所以有時(shí)候也叫它私有函數(shù)。
使用私有函數(shù)有什么好處呢?
- 有助于我們確保全局名字的純凈性,這樣命名沖突的機(jī)會(huì)就很少
- 確保私有性,這使得我們可以選擇只將一些必要的函數(shù)暴露給外部世界,而保留屬于自己的函數(shù),使他們不畏該應(yīng)用程序的其他部分所用。
返回函數(shù)的函數(shù)
正如之前所提到的那樣,函數(shù)始終有一個(gè)返回值,即便不是顯示的返回值么,它也會(huì)隱式的返回一個(gè)undefined,所以既然函數(shù)能返回一個(gè)唯一值,那么自然函數(shù)也能夠返回一個(gè)函數(shù)。函數(shù)跟其他類型的值在本質(zhì)上是一樣的。所以就出現(xiàn)了返回函數(shù)的函數(shù)。
看下面這段代碼
function a() {
alert('a!');
return function () {
alert('b!')
}
}
上面這段代碼,在函數(shù)a中的返回了一個(gè)匿名函數(shù)。
我們調(diào)用這個(gè)函數(shù)
a();
a()();
直接調(diào)用a會(huì)返回a中返回的函數(shù)
a()();的意思是調(diào)用a,在調(diào)用a的返回的函數(shù)。所以最后會(huì)彈出a和b。
能重寫自己的函數(shù)
我們可以在一個(gè)函數(shù)的內(nèi)部重定義該函數(shù)。有兩種方法,一是將函數(shù)的返回值賦予函數(shù)本身,同樣是前面那個(gè)例子
a = a();
只要執(zhí)行上面一句代碼,顯然a酒杯重新定義為他自己的返回函數(shù)了。
還有一種方法就是直接在函數(shù)內(nèi)部重寫自己
function a() {
alert('a!');
a = function() {
alert('b!');
}
}
上面的代碼,當(dāng)我們第一次調(diào)用該函數(shù)是會(huì)有如下的情況發(fā)生。
- alert(‘a(chǎn)’)將會(huì)被執(zhí)行(可以視為一次性的準(zhǔn)備操作)。
- 全局變量a將會(huì)被重定義,并被賦予新的函數(shù)。
而如果該函數(shù)在被調(diào)用的話,被執(zhí)行的九江市alert(b)了。
小結(jié)
下面我們根據(jù)一個(gè)綜合的例子,將上面的幾種函數(shù)綜合到一起
var a = (function () {
function somesetup() {
var setup = 'done';
}
function actualwork() {
alert('worky-worky');
}
somesetup();
return actualwork;
}());
- 我們使用了即時(shí)函數(shù),a在定義的時(shí)候立即調(diào)用了。
- 我們使用了私有函數(shù),somesetup和actualwork兩個(gè)函數(shù)都是私有函數(shù)
- 我們使用了了返回函數(shù)的函數(shù)
- 當(dāng)該函數(shù)第一次調(diào)用時(shí),它會(huì)調(diào)用somesetup并返回函數(shù)變量actualwork的應(yīng)用。請(qǐng)注意,返回值中是不帶括號(hào)的,因此該結(jié)果僅僅是一個(gè)函數(shù)的引用,并不會(huì)產(chǎn)生函數(shù)的調(diào)用。
- 由于這里執(zhí)行語句是以var a = 開頭的所以我們這里也使用了能重寫自己的函數(shù)