1. 程式人生 > >JS的易混淆概念辨析

JS的易混淆概念辨析

在JS中將“(O/o)bject”這個單詞翻譯成物件絕對是最蛋疼的翻譯。很多時候我們我們表述不清就是因為這個詞。先理一下:

1.我們說“物件例項”這個比較明確,就是僅指“一個例項”。而我們說“物件”根據語境有時候是說“物件型別”,有時候是說“物件例項”。

2.“物件型別”這個表述範圍>="Object型別"。JS除基本型別外,還有引用型別。而引用型別又分為(預置)構造型別包裝型別。其中(預置)構造型別有:Object型別,Array型別,Date型別,RegExp型別和Function型別。包裝型別有:Boolean型別,Number型別和String型別。(預置)構造型別和包裝型別可統稱為物件型別(這是我們表面上說的JS裡一切皆物件)。此處的“物件型別”顯然大於"Object型別"。為方便交流,我們說物件型別就指這個統稱,而Object型別就是純粹的Object型別(不用翻譯),不再因Object單詞的翻譯為物件而說其為物件型別。這樣物件型別總是大於Object型別。插一句話,構造型別除了JS已經提供的預置構造型別外,我們可以自定義構造型別

,也就是自定義一個function然後用這個function去new物件(例項)。

3.首字母大寫和小寫有區別: Object偏重指物件型別,object偏重指物件例項; Function和function等同理。我們常說的object物件,其實是指預置或自定義的Object(型別的)物件例項。

4.第2條中的分法是從應用角度分的,如果從生成角度來說,JS是沒有XX型別的,因為從生成角度來說JS裡只有一個個的物件例項(這是我們真正理解的JS裡一切皆物件)。所有的物件(例項)總分為兩類:普通物件(不是由 new Function() 建立的物件,用typeof去檢測時返回“object”)和函式物件

(由 new Function() 建立的物件,用typeof去檢測時返回“function”)。

5.第2條中的XX型別本意是指由構造器函式Object(), Array(), Function()……等new出的物件(例項)的總稱。而這些預置構造器函式包括包裝型別的構造器自定義構造器也是一個物件例項,它們都是new Function()出來的例項。值得注意的是Function()構造器也是new Function()出來的例項,自己生出自己,自己當自己的媽!除了它,別人都是Function()這個媽的孩子。就因為如此,所以Function比較特殊,別人的X.prototype原型物件用typeof求是“object”,而它Function.prototype用typeof求是“function”,我們知道JS中所有函式物件(普通物件沒有)都有prototype屬性

,既然Function.prototype是一個function物件那就仍有原型物件可求,我們在此基礎上再求一次prototype得:typeof Function.prototype.prototype的值為undefined,走到了盡頭。所以,從應用角度來說Function()構造器和其他構造器沒啥兩樣都是平級,但從生成角度來說Function()構造器是其他構造器之母,高一個等級。

6.由第5條可知,JS總是通過一個老物件例項來建立新物件例項,由於是物件創物件故稱其為基於物件的程式設計(OBP),而其他語言比如C++是通過類來例項化物件,故稱為面向物件程式設計(OOP)。由於JS沒有類的概念,所以要用構造器函式模擬類用原型和原型鏈來模擬實現繼承。

7.(先記在這裡以後專門寫原型和原型鏈)x.prototype是x物件的一個屬性,這個屬性可以理解為是一個引用或指標(當然JS裡沒有指標這一概念),它指向一個匿名物件,該匿名物件在我們交流時給它起個名字叫——X Prototype物件,這就是原型物件。(有人說是“物件原型”,這種表述不正規。)我們有時候會直接用x.prototype指代X Prototype這個原型物件(取了名字的匿名物件-_-b),這是方便但不嚴謹的表述方法,需要知道。

8.說一下constructor。在JS中只有函式物件和原型物件真正具有constructor,其他物件不真正具有。但由於這些物件的_proto_屬性指向了原型物件,故其就繼承了consturctor,所以我們可以認為這些物件有constructor。理解了這句話也就知道了繼承就是看_proto_屬性的指向,改變指向就改變了繼承。進而可知修改原型物件重寫(重賦值)原型物件在繼承表現上的區別,及對constructor指向上的影響。

9.最後說一下null。它是JS語言中遺留的bug。null 本應該作為一個獨立的資料型別和值即null純粹就是null,但JS中typeof(null)的值是"object"。我們知道JS中所有物件(無論普通物件還是函式物件)都有_proto_屬性,那你既然是object,我就看看你裡面的_proto_屬性指向哪裡,不過對不起,JS規定null裡沒有_proto_屬性。有兩種方案可以解決這個bug,要麼是給null一個_proto_屬性讓他指回null;要麼是還原null的純粹性而不作為一個object存在。但由於歷史遺留程式碼太多, JS新訂標準拒絕修改此bug,故遺留至今。