5.function類型
函數(shù)實際上是一個對象。因此函數(shù)名的本質(zhì)是一個指向函數(shù)對象的指針。

他并不與某個函數(shù)綁定,這同時也就解釋了將某一個函數(shù)名多次定義,js只會調(diào)用最后一次定義的內(nèi)容。
另外,由于我們說函數(shù)名實際上是一個指向函數(shù)對象的指針,那么這也就意味著同一個函數(shù)可以有多個名字。我們可以在定義一個函數(shù)后,定義另外一個變量 = 之前的指針,這樣同一個函數(shù)就有兩個名字了。因此,函數(shù)名只是指向函數(shù)對象的引用,這個定義非常重要。要訪問函數(shù)指針,只需要訪問變量值,而去掉括號即可。
5.1沒有重載(深入講解)
函數(shù)名是一個指針,他實際上并不與某個函數(shù)綁定,這同時也就解釋了將某一個函數(shù)名多次定義,js只會調(diào)用最后一次定義的內(nèi)容。也就是沒有重載的原因。

5.2函數(shù)聲明和函數(shù)表達(dá)式
在運行js代碼時,解析器和率先讀取到函數(shù)的聲明,并且使其在任何代碼被執(zhí)行前設(shè)置為可訪問狀態(tài)。而真正的函數(shù)表達(dá)式,則必須等到解析器執(zhí)行到了調(diào)用它的具體代碼時,才會被解釋和執(zhí)行。

為了驗證這個結(jié)論,我們可以使用兩種函數(shù)定義的方式,檢查函數(shù)聲明的升格情況:

這是因為賦值的函數(shù)定義并不是函數(shù)聲明,不會在代碼被解釋前執(zhí)行函數(shù)的升格操作。因此在運行到console.log(sum2(a,b))時,sum2并沒有被定義,它也根本沒有指向文中定義的函數(shù)對象,所以報錯sum2 is not a function也不足為奇了。
5.3作為值的函數(shù)
因為我們可以將函數(shù)名看做是指向函數(shù)對象的引用類型變量,因此,可以將函數(shù)作為一個參數(shù)傳遞給另外一個函數(shù),就是理所當(dāng)然的了。

除此之外,在一個函數(shù)中返回另外一個函數(shù)也是非常好的寫法:舉個例子,在一個函數(shù)的連環(huán)定義中,內(nèi)容其實有三個參數(shù):propertyName,object1,object2:

我們可以在外面的函數(shù)中傳入一個propertyName的值,隨后這個函數(shù)會返回一個函數(shù)的定義:
function(object1,object2){? do some things}
此時這個被返回的函數(shù)就可以在別的函數(shù)中作為一個參數(shù)被使用過了:最簡單的使用例子就是我們定義比較函數(shù):

5.4函數(shù)內(nèi)部的屬性
函數(shù)內(nèi)部有兩個特殊屬性:arguments和this。
① arguments我們在前文多次提到過,他是一個類數(shù)組的保存參數(shù)的對象,雖然arguments的主要用途是保存參數(shù)對象,但這個對象其實還有一個叫做callee的屬性,這個屬性是一個引用類型的指針,它指向擁有arguments對象的函數(shù)。
而我們可以使用它,在函數(shù)發(fā)生遞歸時,一旦想要改變函數(shù)名,那么遞歸就會失效,但是使用callee替代原來的函數(shù)名指向函數(shù)就不會有什么問題:

② 函數(shù)內(nèi)部地另外一個特殊對象是this。this是在js編程中經(jīng)常搞不清楚的一點。但是書里有一句清晰的定義,即永遠(yuǎn)記住一句話:this指向的是函數(shù)據(jù)以引用的環(huán)境對象?;蛘哒f,this的值就是據(jù)以執(zhí)行的環(huán)境對象。
換句話說,函數(shù)定義在哪個類里,它所指向的就是哪個類。

對于第一個this.color,因為其定義在全局類里,環(huán)境對象為window,因此color為全局的red。
對于第二個this.color,因為其是從ob1.f()發(fā)起的,環(huán)境對象為ob1,因此this指向ob1,因此color為類內(nèi)的blue。
對于第三個this.color,雖然是在函數(shù)內(nèi)定義,但是因為會發(fā)生函數(shù)定義升格,因此其環(huán)境是全局類,環(huán)境對象為winodw,因此color為全局的red。
但是在這里同時要注意,函數(shù)的名字僅僅是一個包含指針的變量。因此,即便在不同的環(huán)境里,打印color得到不同的值,但其實全局的fun1與ob1.f兩個指針同樣指向一個函數(shù)。二者做邏輯判斷也會返回true。
③ 還有一個函數(shù)屬性叫做caller,它返回調(diào)用當(dāng)前函數(shù)的函數(shù)的引用。定義讀起來很繞,但是看個例子就明白了:

5.5函數(shù)的屬性與方法
前文我們提到過,函數(shù)其實也是對象,因此函數(shù)也有屬性和方法。每個函數(shù)都有兩個屬性:length和protype,以及三個方法:apply和call,和bind。
length為這個函數(shù)在定義時寫入的參數(shù)個數(shù)。
prototype為真正保存引用類型所有實例方法的地方,它是函數(shù)的一個子對象,在第六章會詳細(xì)介紹這個屬性,在這先按下不表。另外,prototype屬性是不可以枚舉的,因此for-in無法發(fā)現(xiàn)該屬性。

apply和call的用途都是在特定的作用域中調(diào)用函數(shù)。實際功能就是設(shè)置函數(shù)體內(nèi)this的值。
apply接受兩個參數(shù):1是特定的作用域,另外一個是參數(shù)數(shù)組。而call與apply唯一的不同僅僅是call是填參數(shù)數(shù)組,而apply是把參數(shù)全部一個一個列進(jìn)去。

首先運行fun2時,this指向window,因此this.c = 10,fun1的結(jié)果也就是13。
當(dāng)將d.f也指向函數(shù)fun2時,this指向了d,因此this.c = 20,fun1的結(jié)果也就變成了23。
apply和call可以有效的指定函數(shù)在何種作用域運行,我們可以首先定義類,再將不同的類作為環(huán)境傳入函數(shù)中去,這時函數(shù)中的this.prototype的值就會變成不同環(huán)境域下的值。
而bind與前二者不同,bind是根據(jù)已有的函數(shù)復(fù)制一個新的函數(shù),而這個新的函數(shù)的作用域和this指向的對象由開發(fā)人員自己決定。一般使用可以分為三個步驟:

另外其實每個函數(shù)也都有toLocaleString,toString,valueOf三個方法,但是因為不同的瀏覽器返回的值不同,但基本上都是函數(shù)實現(xiàn)的內(nèi)容,這些信息在調(diào)試代碼時是比較有用的。在這就不多贅述了。
