06javas對象面向?qū)ο筮€是基于_第1頁
06javas對象面向?qū)ο筮€是基于_第2頁
06javas對象面向?qū)ο筮€是基于_第3頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、06|JavaScript對象:面向?qū)ο筮€是基于對象?06|JavaScript對象:面向?qū)ο筮€是基于對象?你好,我是winter。與其它的語言相比,JavaScript中的“對象”總是顯得不那么合群。一些新人在學(xué)習(xí)JavaScript面向?qū)ο髸r,往往也會有疑惑:為什么JavaScript(直到ES6)有對象的概念,但是卻沒有像其他的語言那樣,有類的概念呢; 為什么在JavaScript對象里可以自由添加屬性,而其他的語言卻不能呢?甚至,在一些爭論中,有人強調(diào):JavaScript并非“面向?qū)ο蟮恼Z言”,而是“基于對象的語言”。這個說法一度流傳甚廣,而事實上,我至今遇到的持有這一說 法的人中,

2、無一能夠回答“如何定義面向?qū)ο蠛突趯ο蟆边@個問題。實際上,基于對象和面向?qū)ο髢蓚€形容詞都出現(xiàn)在了JavaScript標(biāo)準的各個版本當(dāng)中。我們可以先看看JavaScript標(biāo)準對基于對象的定義,這個定義的具體內(nèi)容是:“語言和宿主的基礎(chǔ)設(shè)施由對象來提供,并且JavaScript程序即是一系列互相通訊的 對象集合”。這里的意思根本不是表達弱化的面向?qū)ο蟮囊馑?,反而是表達對象對于語言的重要性。那么,在本篇文章中,我會嘗試讓你去理解面向?qū)ο蠛蚃avaScript中的面向?qū)ο缶烤故鞘裁?。什么是面向?qū)ο??我們先來說說什么是對象,因為翻譯的對象編程的抽象思維有互通之處。,中文語境下我們很難理解“對象”的真正

3、含義。事實上,Object(對象)在英文中,是一切事物的總稱,這和面向中文的“對象”卻沒有這樣的普適性,我們在學(xué)習(xí)編程的過程中,是把它當(dāng)作一個專業(yè)名詞來理解。但不論如何,我們應(yīng)該認識到,對象并不是計算機領(lǐng)域憑空造出來的概念,它是順著人類思維模式產(chǎn)生的一種抽象(于是面向?qū)ο缶幊桃脖徽J為是:更接近 人類思維模式的一種編程范式)。那么,我們先來看看在人類思維模式下,對象究竟是什么。對象這一概念在人類的幼兒期形成,這遠遠早于我們編程邏輯中常用的值、過程等概念。在幼年期,我們總是先認識到某一個蘋果能吃(這里的某一個蘋果就是一個對象),繼而認識到所有的蘋果都可以吃(這里的所有蘋果,就是一個類),再到后來我

4、們才能三個蘋果和三個梨之間的,進而產(chǎn)生數(shù)字“3”(值)的概念。在面向?qū)ο蠓治雠c設(shè)計這本書中,Grady Booch替我們做了總結(jié),他認為,從人類的認知角度來說,對象應(yīng)該是下列事物之一:1. 一個可以觸摸或者可以看見的東西;file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:5306|JavaScript對象:面向?qū)ο筮€是基于對象?2. 人的智力可以理解的東西;3. 可以指導(dǎo)思考或行動(進行想象或施加動作)的東西。有了對象的自然定義后,我們就可以描述編程語言中的對象了。在不同的編程語言中,

5、設(shè)計者也利用各種不同的語言特性來抽象描述對象,最為是使用“類”的方式來描述對象,這誕生了諸如 C+、Java等流行的編程語言。的流派而 JavaScript 早年卻選擇了一個更為冷門的方式:原型(關(guān)于原型,我在下一篇文章會重點介紹,這里你留個印象就可以了)。這是我在前面說它不合群的原因之一。然而很不幸,因為一些公司政治,JavaScript推出之時受管理層之命被要求模仿Java,所以,JavaScript創(chuàng)始人Brendan Eich在“原型運行時”的基礎(chǔ)上引入了new、this等語言特性,使之“看起來更像Java”。在 ES6 出現(xiàn)之前,大量的 JavaScript 程序員試圖在原型體系的基

6、礎(chǔ)上,把JavaScript變得更像是基于類的編程,進而產(chǎn)生了很多所謂的“框架”,比如PrototypeJS、Dojo。事實上,它們成為了某種JavaScript的古怪方言,甚至產(chǎn)生了一系列互不相容的社群,顯然這樣做的是遠遠小于損失的。如果我們從運行時角度來談?wù)搶ο?,就是在討論JavaScript實際運行中的模型,這是由于任何代碼執(zhí)行都必定繞不開運行時的對象模型。不過,幸運的是,從運行時的角度看,可以不必受到這些“基于類的設(shè)施”的困擾,這是因為任何語言運行時類的概念都是被弱化的。首先我們來了解一下JavaScript是如何設(shè)計對象模型的。JavaScript 對象的特征在我看來,不論我們使用什

7、么樣的編程語言,我們都先應(yīng)該去理解對象的本質(zhì)特征(參考Grandy Booch面向?qū)ο蠓治雠c設(shè)計)。總結(jié)來看,對象有如下幾個特點。對象具有唯一標(biāo)識性:即使完全相同的兩個對象,也并非同一個對象。對象有狀態(tài):對象具有狀態(tài),同一對象可能處于不同狀態(tài)之下。對象具有行為:即對象的狀態(tài),可能因為它的行為產(chǎn)生變遷。我們先來看第一個特征,對象具有唯一標(biāo)識性。一般而言,各種語言的對象唯一標(biāo)識性都是用內(nèi)存地址來體現(xiàn)的, 對象具有唯一標(biāo)識的內(nèi)存地址,所以具有唯一的標(biāo)識。所以,JavaScript程序員都知道,任何不同的JavaScript對象其實是互不相等的,我們可以看下面的代碼,o1和o2初看是兩個一模一樣的對象

8、,但是打印出來的 結(jié)果卻是false。var o1 = a: 1 ;var o2 = a: 1 ; console.log(o1 = o2); / false關(guān)于對象的第二個和第三個特征“狀態(tài)和行為”,不同語言會使用不同的術(shù)語來抽象描述它們,比如C+中稱它們?yōu)椤俺蓡T變量”和“成員函數(shù)”,Java中則稱它們 為“屬性”和“方法”。在 JavaScript中,將狀態(tài)和行為統(tǒng)一抽象為“屬性”,考慮到 JavaScript 中將函數(shù)設(shè)計成一種特殊對象(關(guān)于這點,我會在后面的文章中詳細講解,此處先不用file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο?/p>

9、還是基于對象?.html2019/2/10 21:38:5306|JavaScript對象:面向?qū)ο筮€是基于對象?細究),所以 JavaScript中的行為和狀態(tài)都能用屬性來抽象。下面這段代碼其實就展示了普通屬性和函數(shù)作為屬性的一個例子,其中o是對象,d是一個屬性,而函數(shù)f也是一個屬性,盡管寫法不太相同,但是對JavaScript來說,d和f就是兩個普通屬性。var o = d: 1, f() console.log(this.d);所以,總結(jié)一句話來看,在JavaScript中,對象的狀態(tài)和行為其實都被抽象為了屬性。如果你用過Java,一定不要覺得奇怪,盡管設(shè)計思路有一定差別,但是 二者都很

10、好地表現(xiàn)了對象的基本特征:標(biāo)識性、狀態(tài)和行為。在實現(xiàn)了對象基本特征的基礎(chǔ)上, 我認為,JavaScript中對象獨有的特色是:對象具有高度的動態(tài)性,這是因為JavaScript賦予了使用者在運行時為對象添改狀態(tài)和行為的能力。我來舉個例子,比如,JavaScript 定會產(chǎn)生跟我一樣的感受。運行時向?qū)ο筇砑訉傩?,這就跟絕大多數(shù)基于類的、靜態(tài)的對象設(shè)計完全不同。如果你用過Java或者其它別的語言,肯下面這段代碼就展示了運行時如何向一個對象添加屬性,一開始我定義了一個對象o,定義完成之后,再添加它的屬性b,這樣操作是完全沒問題的。var o = a: 1 ;o.b = 2;console.log(o

11、.a, o.b); /1 2為了提高抽象能力,JavaScript的屬性被設(shè)計成比別的語言更加復(fù)雜的形式,它提供了數(shù)據(jù)屬性和JavaScript對象的兩類屬性器屬性(getter/setter)兩類。對JavaScript來說,屬性并非只是簡單的名稱和值,JavaScript用一組特征(attribute)來描述屬性(property)。先來說第一類屬性,數(shù)據(jù)屬性。它比較接近于其它語言的屬性概念。數(shù)據(jù)屬性具有四個特征。value:就是屬性的值。 writable:決定屬性能否被賦值。enumerable:決定for in能否枚舉該屬性。configurable:決定該屬性能否被刪除或者改變特征

12、值。在大多數(shù)情況下,我們只關(guān)心數(shù)據(jù)屬性的值即可。第二類屬性是器(getter/setter)屬性,它也有四個特征。getter:函數(shù)或undefined,在取屬性值時被調(diào)用。setter:函數(shù)或undefined,在設(shè)置屬性值時被調(diào)用。enumerable:決定for in能否枚舉該屬性。configurable:決定該屬性能否被刪除或者改變特征值。file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:5306|JavaScript對象:面向?qū)ο筮€是基于對象?器屬性使得屬性在讀和寫時執(zhí)行代

13、碼,它使用者在寫和讀屬性時,得到完全不同的值,它可以視為一種函數(shù)的語法糖。我們通常用于定義屬性的代碼會產(chǎn)生數(shù)據(jù)屬性,其中的writable、enumerable、configurable都默認為true。我們可以使用內(nèi)置函數(shù)Object.getOwnPropertyDescripter來查看,如以下代碼所示:var o = a: 1 ;o.b = 2;/a和b皆為數(shù)據(jù)屬性O(shè)bject.getOwnPropertyDescriptor(o,"a") / value: 1, writable: true, enumerable: true, configurable: true

14、 Object.getOwnPropertyDescriptor(o,"b") / value: 2, writable: true, enumerable: true, configurable: true我們在這里使用了兩種語法來定義屬性,定義完屬性后,我們用JavaScript的API來查看這個屬性,我們可以發(fā)現(xiàn),這樣定義出來的屬性都是數(shù)據(jù)屬性,writeable、enumerable、configurable都是默認值為true。如果我們要想改變屬性的特征,或者定義器屬性,我們可以使用 Object.defineProperty,示例如下:var o = a: 1

15、;Object.defineProperty(o, "b", value: 2, writable: false, enumerable: false, configurable: true);/a和b都是數(shù)據(jù)屬性,但特征值變化了Object.getOwnPropertyDescriptor(o,"a"); / value: 1, writable: true, enumerable: true, configurable: true Object.getOwnPropertyDescriptor(o,"b"); / value: 2

16、, writable: false, enumerable: false, configurable: trueo.b = 3; console.log(o.b); / 2這里我們使用了Object.defineProperty來定義屬性,這樣定義屬性可以改變屬性的writable和enumerable。我們同樣用Object.getOwnPropertyDescriptor來查看,發(fā)現(xiàn)確實改變了writable和enumerable特征。因為writable特征為false,所以我們重新對b賦值,b的值生變化。發(fā)在創(chuàng)建對象時,也可以使用 get 和 set 關(guān)鍵字來創(chuàng)建var o = get

17、 a() return 1 ;console.log(o.a); / 1器屬性,代碼如下所示:器屬性跟數(shù)據(jù)屬性不同,每次屬性都會執(zhí)行g(shù)etter或者setter函數(shù)。這里我們的getter函數(shù)返回了1,所以o.a每次都得到1。這樣,我們就理解了,實際上JavaScript 對象的運行時是一個“屬性的集合”,屬性以字符串或者Symbol為key,以數(shù)據(jù)屬性特征值或者為value。器屬性特征值對象是一個屬性的索引結(jié)構(gòu)(索引結(jié)構(gòu)是一類常見的數(shù)據(jù)結(jié)構(gòu),我們可以把它理解為一個能夠以比較快的速度用key來查找value的字典)。我們以上面的對 象o為例,你可以想象一下“a”是key。writable:tr

18、ue,value:1,configurable:true,enumerable:true是value。我們在前面的類型課程中,已經(jīng)介紹了Symbol類型,能夠以Symbol為屬性名,這是JavaScript對象的一個特色。講到了這里,如果你理解了對象的特征,也就不難理解我開篇提出來的問題。你甚至可以理解為什么會有“JavaScript不是面向?qū)ο蟆边@樣的說法了。這是由于JavaScript的對象設(shè)計跟目前主流基于類的面向?qū)ο蟛町惙浅4?。file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:

19、5306|JavaScript對象:面向?qū)ο筮€是基于對象?可事實上,這樣的對象系統(tǒng)設(shè)計雖然特別,但是JavaScript提供了完全運行時的對象系統(tǒng),這使得它可以模仿多數(shù)面向?qū)ο缶幊谭妒剑ㄏ乱还?jié)課我們會給你介 紹JavaScript中兩種面向?qū)ο缶幊痰姆妒剑夯陬惡突谠停?,所以它也是正統(tǒng)的面向?qū)ο笳Z言。JavaScript語言標(biāo)準也已經(jīng)明確說明,JavaScript是一門面向?qū)ο蟮恼Z言,標(biāo)準中能這樣說,正是因為JavaScript的高度動態(tài)性的對象系統(tǒng)。所以,我們應(yīng)該在理解其設(shè)計思想的基礎(chǔ)上充分挖掘它的能力,而不是機械地模仿其它語言。結(jié)語要想理解JavaScript對象,必須清空我們腦子里“

20、基于類的面向?qū)ο蟆毕嚓P(guān)的知識,回到人類對對象的樸素認知和面向?qū)ο蟮恼Z言無關(guān)基礎(chǔ)理論,我們就能夠理 解JavaScript面向?qū)ο笤O(shè)計的思路。在這篇文章中,我從對象的基本理論出發(fā),和你理清了關(guān)于對象的一些基本概念,分析了JavaScript對象的設(shè)計思路。接下來又從運行時的角度,介紹了JavaScript對象的具體設(shè)計:具有高度動態(tài)性的屬性集合。很多人在思考JavaScript對象時,會帶著已有的“對象”觀來看問題,最后的結(jié)果當(dāng)然就是“剪不斷理還亂”了。在后面的文章中,我會繼續(xù)帶你探索JavaScript對象的一些機制,看JavaScript如何基于這樣的動態(tài)對象模型設(shè)計礎(chǔ)設(shè)施。你還知道哪些面向

21、對象語言,它們的面向?qū)ο笙到y(tǒng)是怎樣的?請留言告訴我吧!的原型系統(tǒng),以及你熟悉的函數(shù)、類等基file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:5306|JavaScript對象:面向?qū)ο筮€是基于對象?精選留言:37°Cboy 2019-01-29 10:06:55這篇講的思路太好了,追本溯源,娓娓道來。在這里不光能學(xué)到知識活著重溫知識,還有關(guān)于學(xué)習(xí)和講授的方風(fēng)清不揚 2019-01-29 16:46:41php 是世界上最好的編程語言 3贊9贊bitmxy 2019-01-29

22、 07:36:44JS的設(shè)計者原本是個Lisp程序員而且不怎麼喜歡Java面向?qū)ο?,所以採用了原型。在?dāng)時基於原型比基於類的做法要靈活很多。file:/J/geektime/唯一更新/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:5306|JavaScript對象:面向?qū)ο筮€是基于對象?3贊Carson 2019-01-29 10:13:55我暫時接觸的編程有限,JavaScript 是我接觸的第一個面向?qū)ο笳Z言。由于缺少對其他語言的了解,winter在文中的橫向?qū)Ρ龋杏X能讓我更容易理解 JavaScript 的設(shè)計思路,

23、以及 Object 這么設(shè)計的。關(guān)于ECMAScript 2015 加入的 “類”,其實它并不是 JavaScript 新增的面向?qū)ο竽J?,它主要是語法糖的作用,只是一種特殊的函數(shù),背后仍然是基于原型的設(shè)計思路。2贊hhk 2019-01-30 03:14:54關(guān)鍵點在于是否可以在運行時動態(tài)改變對象結(jié)合文章通篇看下來,覺得 JS 的 OO 和他基于類的 OO 不同之處,在于 JS 可以在運行時修改對象,而 class based 的類只能預(yù)先全部定義好,我們并不能在運行時動態(tài)修改類。在我理解來說,條條大路通羅馬,面向?qū)ο笫橇_馬,class based 是一條路,prototype based

24、是另一條路。而且 Symbol 的出現(xiàn),出了許多內(nèi)置接口,讓 JS 又在這條路上走了更遠一些。(以前上學(xué)背面向?qū)ο蟮娜齻€特征,封裝,繼承,多態(tài),現(xiàn)在看一下突然覺得很對。像我這種年輕一點的前端,很可能就只是相對熟悉 JS 而已,對于其他語言只知道 class based 的大概有 Java,C+, C#, Python都是道聽途說,計算機基礎(chǔ)也比較薄弱,所以用來比較其實比較難。另外,好奇 Symbol 是怎么實現(xiàn)的,希望以后能大概講講啦。暫時只想到這些,其他的還在消化 1贊Smallfly 2019-01-29 22:48:10基于類的面向?qū)ο笫褂玫氖抢^承,而 Javascript 更像是組合。

25、 1贊范飯飯 2019-01-29 00:48:23第一 1贊蓮 2019-01-30 15:21:56好像winter沒有回答過同學(xué)的提問,是我沒看見嗎?Marvin 2019-01-30 14:42:06看了這一篇文章,理解了JS中的對象和java,或C+里面的對象的一些區(qū)別,應(yīng)該說最大的區(qū)別就是:JS中的對象,可以設(shè)置器屬性,對吧?還想請問file:/J/geektime/唯一更新:我常聽見周圍學(xué)java或C的朋友說 什么什么一個類,什么什么對象。/ebook/重學(xué)前端/06JavaScript對象:面向?qū)ο筮€是基于對象?.html2019/2/10 21:38:5306|JavaScr

26、ipt對象:面向?qū)ο筮€是基于對象?那他們口中的這個“類”是什么?它和“對象”又有什么區(qū)別?我是科班出身,但所學(xué)專業(yè)和編程并不太相關(guān),參與過前端培訓(xùn),至今已經(jīng)從事前端工作2年了,但我始終覺得些相關(guān)專業(yè)的學(xué)生?;A(chǔ)不扎實,學(xué)東西慢,比不上那請指教夏大偉 2019-01-30 11:28:01我挺喜歡JS,就是因為其動態(tài)性,可能因為我是一個更喜歡自由的人。不過任何事情都有兩面性。這種動態(tài)性也應(yīng)該有一些問題和缺點吧,是什么呢?Error 2019-01-30 10:09:57是否按照犀牛書的順序講解itgou 2019-01-30 07:53:15var o = get a() return 1 ;和 var o=1兩種寫法結(jié)果都是o=1,只是兩種語法糖嗎?或者說哪種情況下會用到第

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論