詳解javascript中的即時(shí)函數(shù),內(nèi)部函數(shù),能重寫自身的函數(shù)

在上篇談到匿名函數(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ù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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