對象是一個包含相關(guān)數(shù)據(jù)和方法的集合(通常由一些變量和函數(shù)組成封豪,我們稱之為對象里面的屬性和方法)灼捂,讓我們通過一個例子來了解它們。
首先, 將oojs.html文件復(fù)制到本地. 此文件包含非常少?— 一個供我們寫源代碼的<script>標(biāo)簽, 一個供我們輸入示例指令的<input>標(biāo)簽片吊,當(dāng)頁面被渲染時, 一些變量定義, 一個輸出任何輸入到<input>的內(nèi)容輸出到<p>標(biāo)簽的函數(shù)。我們用這個文件做為基礎(chǔ)探索對象的基礎(chǔ)語法协屡。
如同Javascript中的很多東西一樣俏脊,創(chuàng)建一個對象通常先定義初始化變量。?嘗試在您已有的文件中JavaScript代碼下面輸入以下內(nèi)容, 保存刷新頁面:
varperson={};
如果你在瀏覽器控制臺輸入person著瓶,然后按下Enter(確認)鍵联予,你會得到如下結(jié)果:
[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] + '.');
? }
};
保存刷新后, 嘗試在你的瀏覽器控制臺輸入下面的內(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?(也可以?看實際效果)余蟹。一個對于初學(xué)者很常見的錯誤是在最后一個成員后面多了一個逗號卷胯,這會引發(fā)錯誤。
所以發(fā)生了什么威酒?一個對象由許多的成員組成窑睁,每一個成員都擁有一個名字(像上面的name、age)葵孤,和一個值(如['Bob', 'Smith']担钮、32)。每一個名字/值(name/value)對被逗號分隔開尤仍,并且名字和值之間由冒號(:)分隔箫津,語法規(guī)則如下所示:
var objectName = {
? member1Name : member1Value,
? member2Name : member2Value,
? member3Name : member3Value
}
對象成員的值可以是任意的,在我們的person對象里有字符串(string)宰啦,數(shù)字(number)苏遥,兩個數(shù)組(array),兩個函數(shù)(function)赡模。前4個成員是資料項目田炭,被稱為對象的屬性(property),后兩個成員是函數(shù)漓柑,允許對象對資料做一些操作教硫,被稱為對象的方法(method)
一個如上所示的對象被稱之為對象的字面量(literal)——手動的寫出對象的內(nèi)容來創(chuàng)建一個對象。不同于從類實例化一個對象辆布,我們會在后面學(xué)習(xí)這種方式栋豫。
當(dāng)你想要傳輸一些有結(jié)構(gòu)和關(guān)聯(lián)的資料時常見的方式是使用字面量來創(chuàng)建一個對象,舉例來說谚殊,發(fā)起一個請求到服務(wù)器以存儲一些數(shù)據(jù)到數(shù)據(jù)庫丧鸯,發(fā)送一個對象要比分別發(fā)送這些數(shù)據(jù)更有效率,而且比起數(shù)組更為易用嫩絮,因為你使用名字(name)來標(biāo)識這些資料丛肢。
在上面的例子中围肥,你使用了點表示法(dot notation)來訪問對象的屬性和方法。對象的名字表現(xiàn)為一個命名空間(namespace)蜂怎,它必須寫在第一位——當(dāng)你想訪問對象內(nèi)部的屬性或方法時穆刻,然后是一個點(.),緊接著是你想要訪問的項目杠步,標(biāo)識可以是簡單屬性的名字(name)氢伟,或者是數(shù)組屬性的一個子元素,又或者是對象的方法調(diào)用幽歼。如下所示:
person.age
person.interests[1]
person.bio()
可以用一個對象來做另一個對象成員的值朵锣。例如將name成員
name : ['Bob', 'Smith'],
改成
name : {
? first : 'Bob',
? last : 'Smith'
},
這樣,我們實際上創(chuàng)建了一個子命名空間甸私,聽起來有點復(fù)雜诚些,但用起來很簡單,你只需要鏈?zhǔn)降脑偈褂靡淮吸c表示法皇型,像這樣:
person.name.first
person.name.last
注意:你需要改變你之前的代碼诬烹,從
name[0]
name[1]
改成
name.first
name.last
否則,你的方法不再有效弃鸦。
另外一種訪問屬性的方式是使用括號表示法(bracket notation)绞吁,替代這樣的代碼
person.age
person.name.first
使用如下所示的代碼:
person['age']
person['name']['first']
這看起來很像訪問一個數(shù)組的元素,從根本上來說是一回事兒唬格,你使用了關(guān)聯(lián)了值的名字掀泳,而不是索引去選擇元素。難怪對象有時被稱之為關(guān)聯(lián)數(shù)組(associative array)了——對象做了字符串到值的映射西轩,而數(shù)組做的是數(shù)字到值的映射。
目前我們僅僅看到了如何訪問對象的成員脑沿,而你其實也可以設(shè)置對象成員的值藕畔,通過聲明你要設(shè)置的成員,像這樣:
person.age = 45
person['name']['last'] = 'Cratchit'
嘗試這些代碼庄拇,然后再查看這些成員是否已經(jīng)被改變了
person.age
person['name']['last']
設(shè)置成員并不意味著你只能更新已經(jīng)存在的屬性的值注服,你完全可以創(chuàng)建新的成員,嘗試以下代碼:
person['eyes'] = 'hazel'
person.farewell = function() { alert("Bye everybody!") }
現(xiàn)在你可以測試你新創(chuàng)建的成員
person['eyes']
person.farewell()
括號表示法一個有用的地方是它不僅可以動態(tài)的去設(shè)置對象成員的值措近,還可以動態(tài)的去設(shè)置成員的名字溶弟。
比如說,我們想讓用戶能夠在他們的數(shù)據(jù)里存儲自己定義的值類型瞭郑,通過兩個input框來輸入成員的名字和值辜御,通過以下代碼獲取用戶輸入的值:
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)在擒权,保存并刷新袱巨,在輸入框里輸入以下代碼:
person.height
這是使用點表示法無法做到的,點表示法只能接受字面量的成員的名字碳抄,不接受變量作為名字愉老。
你也許在我們的方法里注意到了一些奇怪的地方,看這個例子:
greeting: function() {
? alert('Hi! I\'m ' + this.name.first + '.');
}
你也許想知道"this"是什么剖效,關(guān)鍵字"this"指向了當(dāng)前代碼運行時的對象( 原文:the current object the code is being written inside )——這里即指person對象嫉入,為什么不直接寫person呢?當(dāng)你學(xué)到下一篇Object-oriented JavaScript for beginners文章時璧尸,我們開始使用構(gòu)造器(constructor)時咒林,"this"是非常有用的——它保證了當(dāng)代碼的上下文(context)改變時變量的值的正確性(比如:不同的person對象擁有不同的name這個屬性,很明顯greeting這個方法需要使用的是它們自己的name)逗宁。
讓我們以兩個簡單的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 Brain."瞎颗,即使greeting這個方法的代碼是一樣的件甥。就像我們之前說的,this 指向了代碼所在的對象(其實代碼運行時所在的對象)哼拔。在字面量的對象里this看起來不是很有用引有,但是當(dāng)你動態(tài)創(chuàng)建一個對象(例如使用構(gòu)造器)時它是非常有用的,之后你會更清楚它的用途倦逐。
當(dāng)你使用過這些例子之后譬正,你可能會發(fā)現(xiàn)你對點表示法并不陌生,這是因為我們在這個課程里一直在使用它檬姥,每次我們學(xué)習(xí)的示例使用瀏覽器內(nèi)建的API和JavaScript的一些對象時曾我,我們就在使用對象,因為健民,這些功能是由跟我們所看到的對象同樣的結(jié)構(gòu)來構(gòu)建的抒巢,雖然比我們自己定義的要復(fù)雜許多。
所以當(dāng)我們這樣使用字符串的方法時:
myString.split(',');
你正在使用一個字符串實例上可用的方法秉犹,你隨時都可以在代碼里使用字面量創(chuàng)建一個字符串蛉谜,字符串會自動的被創(chuàng)建為字符串(String)的實例,因此會有一些常見的方法和屬性可用崇堵。
當(dāng)你這樣訪問document對象時:
var myDiv = document.createElement('div');
var myVideo = document.querySelector('video');
你正在使用Document實例上可用的方法型诚。每個頁面在加載完畢后,會有一個Document的實例被創(chuàng)建鸳劳,叫做document狰贯,它代表了整個頁面的結(jié)構(gòu),內(nèi)容和一些功能,比如頁面的URL暮现。同樣的还绘,這意味document有一些可用的方法和屬性。
這同樣適用許多其他內(nèi)建的對象或API栖袋,你使用過有——?Array拍顷,Math, 等塘幅。
請注意內(nèi)建的對象或API不會總是自動地創(chuàng)建對象的實例昔案,舉例來說,這個?Notifications API——允許瀏覽器發(fā)起系統(tǒng)通知电媳,需要你為每一個你想發(fā)起的通知都使用構(gòu)造器進行實例化踏揣。嘗試在JavaScript終端里輸入以下代碼
var myNotification = new Notification('Hello!');
我們會在之后的文章里學(xué)習(xí)到構(gòu)造器。
Note: 這樣來理解對象之間通過消息傳遞來通信是很有用的——當(dāng)一個對象想要另一個執(zhí)行某種動作時匾乓,它通常會通過那個對象的方法給其發(fā)送一些信息捞稿,并且等待回應(yīng),即我們所知的返回值拼缝。