淺析JavaScript的對象系統(tǒng)

之前在《JavaScript的數(shù)據(jù)類型》這篇文章里說過,Object對于JavaScript的語言結(jié)構(gòu)來說意義不一般括饶。為什么這么說呢?你肯定在不少地方看到過這句話:JavaScript中一切皆對象入录。這句話沒什么錯。你知道佳镜,JS連函數(shù)都有其屬性和方法僚稿;當你定義一個基本類型值的字符串,可是你卻可以將這個作為基本類型值的字符串當作對象一樣去調(diào)用substr()方法蟀伸。你有想過其中的原因嗎蚀同?一切的答案都在JavaScript對象系統(tǒng)(聲明一下缅刽,JavaScript對象系統(tǒng)這個詞并不是什么統(tǒng)一定義,只是感覺在這里這么叫比較合適蠢络。)中衰猛。

請看下面這張圖。

JS對象系統(tǒng).png

這張結(jié)構(gòu)圖其實不規(guī)范刹孔,也并不完善啡省,但是用來整體性地理解JS的Obejct是沒問題的。下面就結(jié)合圖來分析一下JS對象系統(tǒng)的結(jié)構(gòu)髓霞。

  • 本地對象(native object)

圖中的“本地對象”這個叫法并不唯一卦睹,也可以叫做“原生對象”、“內(nèi)置對象”方库、“內(nèi)建對象”结序,但其實指的都是 native object。不必糾結(jié)這個纵潦,只是翻譯不一導致叫法上的差異 - -徐鹤,其實想表達的意思都是一致的。ECMA-262對于native object的定義為:

獨立于宿主環(huán)境的 ECMAScript 實現(xiàn)提供的對象

我們知道邀层,“宿主”一般指瀏覽器凳干,而“獨立于宿主環(huán)境”,也就是說與瀏覽器環(huán)境不相關被济,這就是說:native object與瀏覽器不相關救赐,只要這個瀏覽器按照 ECMAScript 規(guī)范實現(xiàn)了JS,那就必然實現(xiàn)了規(guī)范中的所有native object只磷。換句話說就是:本地對象(native object)是語言本身實現(xiàn)和提供的對象经磅,和語言運行在哪個環(huán)境無關。也就是說钮追,不管你的JS代碼在哪里跑预厌,你都可以new出 native object 并使用它。照此理解元媚,我覺得其實把 native object 翻譯成“原生對象”最合意轧叽。

  • Object

到目前為止,我們看到的大多數(shù)引用類型值都是 Object 類型的實例刊棕;而且炭晒,Object 也是 ECMAScript 中使用最多的一個類型。雖然 Object 的實例不具備多少功能甥角,但對于在應用程序中存儲和傳輸數(shù)據(jù)而言网严,它們確實是非常理想的選擇∴臀蓿——《JavaScript高級程序設計(第3版)》

所有其他對象類型的基礎類型震束。提供了toString()等基礎方法怜庸。

  • Array

ECMAScript定義的數(shù)組類型。

  • Date

ECMAScript定義的日期類型垢村。

  • RegExp

ECMAScript定義的正則類型割疾。

  • Function

說起來 ECMAScript 中什么最有意思,我想那莫過于函數(shù)了——而有意思的根源嘉栓,則在于函數(shù)實際上是對象杈曲。每個函數(shù)都是 Function 類型的實例,而且都與其他引用類型一樣具有屬性和方法胸懈〉F耍——《J3》

沒錯,F(xiàn)unction 是一種對象類型趣钱,function 是一個對象實例涌献。見如下代碼:

console.log(Function() instanceof Function);    //true(構(gòu)造函數(shù)Function()是Function類型的實例)
console.log(Function() instanceof Object);    //true(構(gòu)造函數(shù)Function()當然也是Object類型的實例)

事實上,任何一個函數(shù)都是函數(shù)對象的實例首有,而函數(shù)類型本身就是一種對象類型燕垃,所以:函數(shù)也是對象。

  • Error 等各種錯誤類對象

Error井联、EvalError卜壕、RangeError、ReferenceError烙常、SyntaxError轴捎、TypeError、URIError 等錯誤類型的對象蚕脏。

  • String Number Boolean

為了方便操作對應的3種基本類型值而定義的3種對象類型侦副,使得可以像使用對象一般操作字符串、數(shù)值驼鞭、布爾值秦驯。請理解一下下面的代碼:

var str = new String();
str.detail = '我是字符串,但實際上是一個對象挣棕,否則我怎么可以設置屬性译隘?';
console.log(str);    //String {detail: "我是字符串,但實際上是一個對象洛心,否則我怎么可以設置屬性固耘?", length: 0, [[PrimitiveValue]]: ""}
console.log(str.detail);    //'我是字符串,但實際上是一個對象皂甘,否則我怎么可以設置屬性玻驻?'

前面說到過,你聲明并初始化一個字符串后偿枕,通常會理所應當?shù)貙⑵湟暈橐粋€對象直接使用:

var str = 'Hello World';
str = str.substr(0,5);    //調(diào)用substr()方法截取字符串
console.log(str);    //'Hello'

代碼沒有任何問題璧瞬,我們也經(jīng)常這么寫。但稍微思考一下你就會發(fā)現(xiàn)渐夸,str本身作為一個字符串嗤锉,它只是一個基本數(shù)據(jù)類型的值,憑什么可以像一個對象一樣直接調(diào)用方法墓塌?講道理瘟忱,str僅僅是一個值,哪里來的什么substr()方法苫幢?原因就在對象系統(tǒng)中的那個基本包裝類型對象访诱。

實際上,每當讀取一個基本類型值的時候韩肝,后臺就會創(chuàng)建一個對應的基本包裝類型的對象触菜,從而讓我們能夠調(diào)用一些方法來操作這些數(shù)據(jù) ——《J3》

書上一語道明。注意一下這句話中的“讀取”和“對應”兩個詞哀峻∥邢啵“讀取”是指進入讀取模式,即從內(nèi)存中去讀取這個字符串值的時候剩蟀;“對應”指的是基本類型值是哪種類型催蝗,后臺自動給你創(chuàng)建的基本包裝類型就是哪種對應的類型,比如這里的基本類型值是String類型育特,那后臺創(chuàng)建的基本包裝類型也就是String包裝類型丙号。

因為這一機制,上面代碼的實際執(zhí)行情況其實是這樣的:

var str = 'Hello World';
//str = str.substr(0,5);    //(str進入讀取模式缰冤,準備創(chuàng)建基本包裝類型對象)

var _str = new String('Hello World');
str = _str.substr(0, 5);
_str = null;    //使用完后臺會立即將該包裝對象銷毀

console.log(str);    //'Hello'

這里分析的是String包裝類型槽袄,還有Number包裝類型和Boolean包裝類型也是完全一樣的原理。

  • 內(nèi)置對象(單體內(nèi)置對象)(built-in object)

又來一個內(nèi)置對象锋谐?別混淆遍尺,這個是 built-in object ,上面說過的那個是 native object 涮拗。要怪就怪漢語博大精深乾戏,這兩個詞你來給我翻一下 - - ∪龋《J3》這本書上又將 built-in object 定義為“單體內(nèi)置對象”鼓择,我也搞不懂這個“單體”又是什么意思。就漾。

ECMA-262對內(nèi)置對象的定義是:“由ECMAScript實現(xiàn)提供的呐能、不依賴于宿主環(huán)境的對象,這些對象在ECMAScript程序執(zhí)行之前就已經(jīng)存在了“诔觯”意思就是說朗徊,開發(fā)人員不必顯式地實例化內(nèi)置對象,因為它們已經(jīng)實例化了偎漫∫遥——《J3》

這是ECMA-262對于 built-in object 的定義。對比 native object 的定義:“獨立于宿主環(huán)境的 ECMAScript 實現(xiàn)提供的對象”象踊,可以看出温亲,built-in object 是更加特殊的 native object,built-in object 屬于 native object杯矩。

ECMA-262定義了兩種 built-in object:Global對象栈虚、Math對象。

Global對象

事實上史隆,js中并不存在所謂的全局變量以及完全獨立的函數(shù)魂务。沒錯,你定義的所有全局變量其實都是Global對象的屬性逆害,你在全局作用域下定義的所有函數(shù)其實都是Global對象的方法头镊。

ECMAScript中的 Global 對象在某種意義上是作為一個終極的“兜底兒對象” 來定義的。換句話說魄幕,不屬于任何其他對象的屬性和方法相艇,終都是它的屬性和方法。事實上纯陨,沒有全局變量或全局函數(shù)坛芽;所有在全局作用域中定義的屬性和函數(shù),都是 Global 對象的屬性翼抠×——《J3》

parseInt()eval()阴颖、encodeURIComponent()這些函數(shù)實際上都是Global對象的方法活喊,在使用這些方法的時候無需通過對象去調(diào)用,直接就可以使用量愧。引文說過:“這些對象在ECMAScript程序執(zhí)行之前就已經(jīng)存在了钾菊。”這也算 build-in object 的一個特別之處偎肃,《J3》將 build-in object 定義為“單體內(nèi)置對象”煞烫,這個“單體”是否就是指無需手動實例化這一點?

Global對象的所有屬性如下表:

Global對象的屬性

好吧累颂,特殊值undefined居然是Global對象的一個屬性值 - -滞详。乍看之下可能會有點詫異,不過仔細想想,我們之所以說JavaScript中一切皆對象是有原因的料饥,你看蒲犬,就連undefined都是對象的屬性值。從表中還可以看到稀火,所有原生引用類型的構(gòu)造函數(shù)也都是Global對象的屬性暖哨。這怎么理解赌朋?其實也很好理解凰狞,比如說當你想要創(chuàng)建一個日期類型的變量時,直接上構(gòu)造函數(shù)var date = new Date();就可以了沛慢,可是你想過沒有赡若,Date()構(gòu)造函數(shù)本身是一個函數(shù),而前面我們說過团甲,JS并不存在完全獨立的函數(shù)逾冬,任何函數(shù)其實都是掛在某個對象下的方法,哪怕它是一個構(gòu)造函數(shù)躺苦。而這些原生構(gòu)造函數(shù)身腻,其“掛載”的對象正是Global對象。

介紹了這么多關于Global對象的內(nèi)容匹厘,是不是還是不清楚它是個什么玩意兒嘀趟?這是因為我們在瀏覽器中并不能直接訪問這個對象。好在瀏覽器為我們實現(xiàn)了一個包含了Global對象的window對象愈诚。

ECMAScript 雖然沒有指出如何直接訪問 Global 對象她按,但 Web 瀏覽器都是將這個全局對象作為 window 對象的一部分加以實現(xiàn)的。因此炕柔,在全局作用域中聲明的所有變量和函數(shù)酌泰,就都成為了 window 對象的屬性∝袄郏——《J3》

window對象包含了Global對象的所有內(nèi)容陵刹,同時擴展了大量自身需要的屬性和方法(比如常用的alert())。因此欢嘿,在瀏覽器中我們可以通過window對象隨意訪問上述的屬性和方法衰琐。請看下面代碼并加以理解:

var date = new window.Date();    //window是對Global對象的擴展實現(xiàn),構(gòu)造函數(shù)Date()確實是掛在window上面的
console.log(date);    //Thu Jul 21 2016 16:52:08 GMT+0800 (中國標準時間)

你可以自己再做下測試际插,控制臺打印一下window碘耳,可以發(fā)現(xiàn)它確確實實包含了上述的所有屬性和構(gòu)造函數(shù)。

Math對象

Math對象是一個保存著必要的數(shù)學操作的 build-in object框弛。里面保存著常量e辛辨、圓周率π等的值作為屬性,同時提供了取整Math.floor()、取隨機數(shù)Math.random()斗搞、求平方根等等數(shù)學方法指攒。和Global對象一樣,這些屬性和方法都可以在任何時候任何地方直接訪問和調(diào)用僻焚,只不過其形式統(tǒng)一為:Math.***允悦。

宿主對象(host object)


宿主對象是指宿主環(huán)境所實現(xiàn)和提供的對象。所有非本地對象(native object)都是宿主對象虑啤。我之所以在結(jié)構(gòu)圖中把自定義對象掛到了宿主對象下正是基于此隙弛,不過這并非定死的,你若將自定義對象拎出來和本地對象狞山、宿主對象并列放也并非不可全闷。

所謂宿主,就是指JS代碼所在的運行環(huán)境萍启。對于瀏覽器環(huán)境而言总珠,我們顯示一個頁面需要HTML,所以瀏覽器實現(xiàn)了DOM對象 —— window.document勘纯;我們還需要瀏覽器本身給我們提供一些必要的東西局服,比如URL地址相關的location、設備屏幕相關的screen等驳遵,所以瀏覽器又為我們提供了BOM對象 —— window淫奔。這些對象,就是host object超埋。

等等搏讶,怎么window對象又出場了?上面不是說過了霍殴,window對象是瀏覽器對Global對象的擴展實現(xiàn)媒惕,是Global對象的超集,那這玩意兒究竟該掛到build-in object上来庭,還是宿主對象下的BOM上妒蔚?答案當然是后者≡鲁冢可以明確的是肴盏,window對象本就是瀏覽器所實現(xiàn)的,那它當然屬于瀏覽器對象模型(BOM)了帽衙!只不過菜皂,window把ECMAScript規(guī)定的Global對象也給一并實現(xiàn)了而已。還有厉萝,DOM對象即是window.document恍飘,而window.document就是DOM的根節(jié)點榨崩,從這點來講,我們可以理解為BOM包含了DOM 章母。

如此母蛛,我們終于找到最終對象了 - -,它正是 BOM —— window乳怎。你幾乎可以在這個對象中找到一切彩郊。全局變量、自定義對象蚪缀、JSON對象(ECMA262-5引入為規(guī)范)秫逝、Math對象、原生構(gòu)造函數(shù)椿胯、Global的東西筷登。剃根。哩盲。

萬物合一,世界清靜了狈醉。

最后廉油,可以把最開始給的圖修正更新一下了:

QQ截圖20160722114051.png

(注:ECMA262-5已將JSON對象納入native object)

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市苗傅,隨后出現(xiàn)的幾起案子抒线,更是在濱河造成了極大的恐慌,老刑警劉巖渣慕,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘶炭,死亡現(xiàn)場離奇詭異,居然都是意外死亡逊桦,警方通過查閱死者的電腦和手機眨猎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强经,“玉大人睡陪,你說我怎么就攤上這事∧淝椋” “怎么了兰迫?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長炬称。 經(jīng)常有香客問我汁果,道長,這世上最難降的妖魔是什么玲躯? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任据德,我火速辦了婚禮鲸伴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晋控。我一直安慰自己汞窗,他們只是感情好,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布赡译。 她就那樣靜靜地躺著仲吏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝌焚。 梳的紋絲不亂的頭發(fā)上裹唆,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音只洒,去河邊找鬼许帐。 笑死,一個胖子當著我的面吹牛毕谴,可吹牛的內(nèi)容都是我干的成畦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼涝开,長吁一口氣:“原來是場噩夢啊……” “哼循帐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舀武,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤拄养,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后银舱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘪匿,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年寻馏,在試婚紗的時候發(fā)現(xiàn)自己被綠了棋弥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡操软,死狀恐怖嘁锯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情聂薪,我是刑警寧澤家乘,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站藏澳,受9級特大地震影響仁锯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翔悠,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一业崖、第九天 我趴在偏房一處隱蔽的房頂上張望野芒。 院中可真熱鬧,春花似錦双炕、人聲如沸狞悲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摇锋。三九已至,卻和暖如春站超,著一層夾襖步出監(jiān)牢的瞬間荸恕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工死相, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留融求,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓算撮,卻偏偏與公主長得像生宛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钮惠,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

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

  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,233評論 0 4
  • ECMAScript關鍵字 delete do else finally function in instance...
    doudou2閱讀 721評論 0 0
  • 本章內(nèi)容 理解對象屬性 理解并創(chuàng)建對象 理解繼承 面向?qū)ο笳Z言有一個標志茅糜,那就是它們都有類的概念,而通過類可以創(chuàng)建...
    悶油瓶小張閱讀 851評論 0 1
  • 中山有女嬌無雙素挽,清眸皓齒垂明珰。 我出生于南京狸驳,父親是做官的预明,卻是不幸早亡,家財被吞沒耙箍,我和妹妹流落街頭撰糠。 我只好...
    問心淺笑閱讀 401評論 12 11
  • 裴晨旭,現(xiàn)年33歲辩昆,2008年畢業(yè)于鄭州大學升達經(jīng)貿(mào)學院財務管理專業(yè)阅酪,同年到我院財務科參加工作,第二年調(diào)至...
    平_fe98閱讀 1,249評論 12 8