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