前提: | 基礎(chǔ)計(jì)算機(jī)基礎(chǔ), 了解基礎(chǔ)的HTML 和 CSS, 熟悉 JavaScript 基礎(chǔ) (基礎(chǔ)知識(shí)看這里?First steps 和這里?Building blocks). |
---|---|
目標(biāo): | 理解面相對(duì)象編程背后的基礎(chǔ)理論, 怎樣理解 JavaScript ("一切皆對(duì)象most things are objects"), 如何開始使用JavaScript對(duì)象. |
首先, 將?oojs.html?文件復(fù)制到本地. 此文件包含非常少?— 一個(gè)供我們寫源代碼的?<script>
標(biāo)簽, 一個(gè)供我們輸入示例指令的 <input>
標(biāo)簽,當(dāng)頁(yè)面被渲染時(shí), 一些變量定義, 一個(gè)輸出任何輸入到<input>
的內(nèi)容輸出到<p>
標(biāo)簽的函數(shù)。我們用這個(gè)文件做為基礎(chǔ)探索對(duì)象的基礎(chǔ)語(yǔ)法.
如同Javascript中的很多東西一樣,創(chuàng)建一個(gè)對(duì)象通常先定義初始化變量。?嘗試在您已有的文件中JavaScript代碼下面輸入以下內(nèi)容, 保存刷新頁(yè)面:
var person = {};
如果你在input標(biāo)簽里輸入person然后點(diǎn)擊按鈕, 你會(huì)得到如下結(jié)果:
[object Object]
恭喜你, 你剛創(chuàng)建了你的第一個(gè)對(duì)象. 干的漂亮! 但這是一個(gè)空對(duì)象,所以我們做不了更多的事情。像下面一樣更新下我們的對(duì)象:
var person = { name : ['Bob', 'Smith'], age : 32, gender : 'male', interests : ['music', 'skiing'], bio : function() { alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.'); }, greeting: function() { alert('Hi! I\'m ' + this.name[0] + '.'); } };
保存刷新后, 嘗試在你的input標(biāo)簽里輸入下面的內(nèi)容:
person.name[0] person.age person.interests[1] person.bio() person.greeting()
現(xiàn)在在你的對(duì)象里得到了一些數(shù)據(jù)和功能(functionality),現(xiàn)在可以通過(guò)簡(jiǎn)單的語(yǔ)法訪問(wèn)他們了!
Note:如果做上面的東西遇到了麻煩,嘗試拿你的代碼與我們的版本做對(duì)比——對(duì)比?oojs-finished.html (也可以?see it running live). One common mistake when you are starting out with objects is to put a comma on the end of the last member — this will cause an error.
那么這里發(fā)生了什么? 嗯,一個(gè)對(duì)象由多個(gè)成員組成,每個(gè)成員有一個(gè)名稱(例如上面的 name
和 age
)和一個(gè)值(例如 [\'Bob
\',\'Smith\'] 和 32
)。 每個(gè)名稱/值對(duì)必須用逗號(hào)分隔,每種情況下的名稱和值都用冒號(hào)分隔。 語(yǔ)法總是遵循此模式:
var objectName = { member1Name : member1Value, member2Name : member2Value, member3Name : member3Value }
對(duì)象成員的值可以是任何東西 - 在我們的person對(duì)象中,我們有一個(gè)字符串,數(shù)字,兩個(gè)數(shù)組和兩個(gè)函數(shù)。 前四個(gè)項(xiàng)目是數(shù)據(jù)項(xiàng),被稱為對(duì)象的屬性。 最后兩個(gè)項(xiàng)目是允許對(duì)象用該數(shù)據(jù)做某事的函數(shù),并且被稱為對(duì)象的方法。
像這樣的對(duì)象被稱為對(duì)象字面量 - 我們已經(jīng)逐字地寫出了對(duì)象內(nèi)容,因?yàn)槲覀儊?lái)創(chuàng)建它。 這與從類實(shí)例化的對(duì)象相反,稍后我們將討論。
當(dāng)您希望以某種方式傳輸一系列結(jié)構(gòu)化的相關(guān)數(shù)據(jù)項(xiàng)時(shí),使用對(duì)象常量創(chuàng)建對(duì)象是很常見的,例如向服務(wù)器發(fā)送要放入數(shù)據(jù)庫(kù)的請(qǐng)求。 發(fā)送單個(gè)對(duì)象比分別發(fā)送多個(gè)項(xiàng)要有效得多,并且當(dāng)您想要按名稱標(biāo)識(shí)各個(gè)項(xiàng)時(shí),它比數(shù)組更容易使用。
上面,您使用點(diǎn)符號(hào)訪問(wèn)了對(duì)象的屬性和方法。 對(duì)象名稱(人)充當(dāng)命名空間 - 必須首先輸入該對(duì)象才能訪問(wèn)對(duì)象中的任何封裝的。 接下來(lái)你寫一個(gè)點(diǎn),然后你想訪問(wèn)的項(xiàng)目 - 這可以是一個(gè)簡(jiǎn)單的屬性的名稱,數(shù)組屬性的一個(gè)項(xiàng)目,或者調(diào)用一個(gè)對(duì)象的方法,例如:
person.age person.interests[1] person.bio()
甚至可以使對(duì)象的值成為另一個(gè)對(duì)象。 例如,嘗試更改名稱成員
name : ['Bob', 'Smith'],
至
name : { first : 'Bob', last : 'Smith' },
這里我們有效地創(chuàng)建了子命名空間。 這聽起來(lái)很復(fù)雜,但真的不是 - 訪問(wèn)這些項(xiàng)目,你只需要鏈接額外的步驟到另一個(gè)點(diǎn)的末端。 試試這些:
person.name.first person.name.last
重要:此時(shí),您還需要完成方法代碼并更改任何實(shí)例
name[0] name[1]
至
name.first name.last
否則你的方法將不再工作。
還有另一種方法來(lái)訪問(wèn)對(duì)象屬性 - 使用括號(hào)符號(hào)。 而不是使用這些:
person.age person.name.first
您可以使用
person['age'] person['name']['first']
這看起來(lái)非常類似于如何訪問(wèn)數(shù)組中的項(xiàng)目,它基本上是一樣的東西 - 而不是使用索引號(hào)來(lái)選擇一個(gè)項(xiàng)目,你使用的名稱與每個(gè)成員的值相關(guān)聯(lián)。 難怪對(duì)象有時(shí)被稱為關(guān)聯(lián)數(shù)組 - 它們以數(shù)組將數(shù)字映射到值的相同方式將字符串映射到值。
到目前為止,我們只看到檢索(或獲取)對(duì)象成員 - 您還可以設(shè)置(更新)對(duì)象成員的值,只需聲明您想要的成員 設(shè)置(使用點(diǎn)或括號(hào)表示法),如下所示:
person.age = 45 person['name']['last'] = 'Cratchit'
嘗試輸入這些行,然后再次獲取成員,以查看他們?nèi)绾胃淖?
person.age person['name']['last']
設(shè)置成員不僅僅停止更新現(xiàn)有屬性和方法的值; 您還可以創(chuàng)建完全新的成員。 試試這些:
person['eyes'] = 'hazel' person.farewell = function() { alert("Bye everybody!") }
您現(xiàn)在可以測(cè)試您的新成員:
person['eyes'] person.farewell()
括號(hào)表示法的一個(gè)有用的方面是它可以用于動(dòng)態(tài)設(shè)置成員值,但也可以設(shè)置成員名。 假設(shè)我們希望用戶能夠通過(guò)在兩個(gè)文本輸入中鍵入成員名稱和值,將自定義值類型存儲(chǔ)在其人員數(shù)據(jù)中? 我們可以得到這樣的值:
var myDataName = nameInput.value var myDataValue = nameValue.value
我們可以將這個(gè)新的成員名和值添加到 person
對(duì)象,如下所示:
person[myDataName] = myDataValue
要測(cè)試這一點(diǎn),請(qǐng)嘗試將以下行添加到代碼中,位于 person
對(duì)象的結(jié)束大括號(hào)下面:
var myDataName = 'height' var myDataValue = '1.75m' person[myDataName] = myDataValue
現(xiàn)在嘗試保存和刷新,并在文本輸入中輸入以下內(nèi)容:
person.height
這是不可能的點(diǎn)符號(hào),它只能接受文字成員名稱,而不是指向名稱的變量值。
你可能已經(jīng)注意到我們的方法中有些奇怪的東西。 看看這個(gè)例子:
greeting: function() { alert('Hi! I\'m ' + this.name.first + '.'); }
你可能想知道"這個(gè)"是什么。 this
關(guān)鍵字指的是代碼被寫入的當(dāng)前對(duì)象 - 因此在這種情況下此
等效于 person
。 那么為什么不直接寫 person
呢? 您將在面向初學(xué)者的面向?qū)ο驤avaScript 文章中看到,當(dāng)我們開始創(chuàng)建構(gòu)造函數(shù)等時(shí), this
是非常有用的 - 它將始終確保在成員的上下文改變時(shí)使用正確的值(例如,兩個(gè)不同的 person
對(duì)象實(shí)例可能具有不同的名稱,但是在說(shuō)出他們的問(wèn)候語(yǔ)時(shí)想要使用自己的名稱 )。
讓我們用簡(jiǎn)化的人物對(duì)象來(lái)說(shuō)明我們的意思::
var person1 = { name : 'Chris', greeting: function() { alert('Hi! I\'m ' + this.name + '.'); } } var person2 = { name : 'Brian', greeting: function() { alert('Hi! I\'m ' + this.name + '.'); } }
在這種情況下, person1.greeting()
會(huì)輸出"Hi!I\'m Chris。 person2.greeting()
另一方面將輸出"Hi!I\'m Brian。",即使方法的代碼在每種情況下是完全相同的。 正如我們前面所說(shuō),這個(gè)
等于代碼所在的對(duì)象 - 當(dāng)你用手寫出對(duì)象字面量時(shí),這不是非常有用,但是當(dāng)你動(dòng)態(tài)地 生成對(duì)象(例如使用構(gòu)造函數(shù))。 這將變得更清楚以后。
正如你經(jīng)歷過(guò)這些例子,你可能一直認(rèn)為你使用的點(diǎn)符號(hào)是非常熟悉的。 這是因?yàn)槟阍谡麄€(gè)課程中一直使用它! 每次我們通過(guò)一個(gè)使用內(nèi)置瀏覽器API或JavaScript對(duì)象的示例,我們一直使用對(duì)象,因?yàn)檫@些功能使用完全相同的對(duì)象結(jié)構(gòu),我們?cè)谶@里看到 ,雖然比我們自己的定制例子更復(fù)雜。
所以當(dāng)你使用字符串方法如:
myString.split(',');
您正在使用 字符串的實(shí)例上提供的方法
> 類。 每次在代碼中創(chuàng)建一個(gè)字符串時(shí),該字符串將自動(dòng)創(chuàng)建為 String
的一個(gè)實(shí)例,因此有幾個(gè)常用的方法/屬性可供使用。
當(dāng)你使用這樣的行訪問(wèn)文檔對(duì)象模型時(shí):
var myDiv = document.createElement('div'); var myVideo = document.querySelector('video');
您正在使用 文檔
實(shí)例上提供的方法, 類。 對(duì)于每個(gè)加載的網(wǎng)頁(yè),創(chuàng)建 Document
的實(shí)例,稱為 document
,代表整個(gè)頁(yè)面的結(jié)構(gòu),內(nèi)容和其他功能, 再次,這意味著它有幾個(gè)常用的方法/屬性可用。
幾乎任何其他內(nèi)置的對(duì)象/ API,你一直在使用 - / Global_Objects / Array"> Array
, > Math
等。
注意,內(nèi)置的Objects / APIs不總是自動(dòng)創(chuàng)建對(duì)象實(shí)例。 例如,通知API (允許新型瀏覽器觸發(fā)系統(tǒng)通知)需要 您可以使用要觸發(fā)的每個(gè)通知的構(gòu)造函數(shù)來(lái)實(shí)例化一個(gè)新的對(duì)象實(shí)例。 嘗試在您的JavaScript控制臺(tái)中輸入以下內(nèi)容:
var myNotification = new Notification('Hello!');
同樣,我們將在后面的文章中討論構(gòu)造函數(shù)。
注意:考慮對(duì)象以消息傳遞的方式進(jìn)行通信是很有用的 - 當(dāng)對(duì)象需要其他對(duì)象執(zhí)行某種操作時(shí),它會(huì)向其他對(duì)象發(fā)送消息 通過(guò)它的一個(gè)方法,并等待一個(gè)響應(yīng),我們知道作為一個(gè)返回值。
恭喜,您已經(jīng)達(dá)到我們的第一個(gè)JS對(duì)象文章的結(jié)束 - 您現(xiàn)在應(yīng)該知道如何使用JavaScript中的對(duì)象 - 包括創(chuàng)建自己的簡(jiǎn)單對(duì)象。 您還應(yīng)該明白,對(duì)象作為存儲(chǔ)相關(guān)數(shù)據(jù)和功能的結(jié)構(gòu)是非常有用的 - 如果您試圖將我們的 person
對(duì)象中的所有屬性和方法作為單獨(dú)的變量和函數(shù)進(jìn)行跟蹤, 低效和令人沮喪的,我們會(huì)冒著與其他變量和函數(shù)沖突的風(fēng)險(xiǎn)與同名。 對(duì)象讓我們保持信息安全地鎖在自己的包,從危害的方式。
在下一篇文章中,我們將開始討論面向?qū)ο缶幊?OOP)理論,以及如何在JavaScript中使用這種技術(shù)。
更多建議: