在JavaScript中,物件是Object的實例。你可以如下建立一個新的物件:
var obj = new Object();
實際上,現在已經很少人這麼撰寫了,使用物件實字(Object literal)語法就可以建立一個物件:
var obj = {};
兩者的作用相同,物件實字寫法顯然較有效率。在JavaScript中,你可以隨時為物件新增特性(Properties),也可以隨時用delete運算子來刪除特性。例如:
js> var obj = {};
js> obj.x = 10;
10
js> delete obj.x;
true
js>
js> obj.x = 10;
10
js> delete obj.x;
true
js>
若刪除成功,delete會傳回true,並非所有特性都可被delete刪除,有些內建特性可能無法被刪除(例如在瀏覽器中的一些特性)。附帶一提的是,delete作用在非物件特性或變數時,會傳回true。例如delete 1;就會傳回true。
如果事先知道物件的特性,可以使用物件實字一併建立。例如:
js> var obj = {
> x : 10,
> y : 20
> };
js> obj.x;
10
js> obj.y;
20
js>
> x : 10,
> y : 20
> };
js> obj.x;
10
js> obj.y;
20
js>
想要知道物件上有哪些自定義特性,可以使用for in語法,逐一取出物件的特性名稱。例如:
js> for(var prop in obj) {
> print(prop);
> print(typeof prop);
> }
x
string
y
string
js> 'x' in obj;
true
js>
> print(prop);
> print(typeof prop);
> }
x
string
y
string
js> 'x' in obj;
true
js>
由以上也可以得知,每個特性名稱其實是字串型態,這也說明了,如果想用in測試某特性時,特性名稱必須以字串指定。
事實上,點運算子(.)只是存取物件特性的一種方式。你也可以使用[]運算子來存取特性。例如:
js> var obj = {};
js> obj['x'] = 10;
10
js> obj.x;
10
js> obj['x'];
10
js>
js> obj['x'] = 10;
10
js> obj.x;
10
js> obj['x'];
10
js>
JavaScript的物件本質上,其實是個特性與值的群集(Collection),要比喻的話,就像是Java中的Map物件。如果你要使用for in取得物件上的特性與值,則可以如下:
js> var obj = {
> x : 10,
> y : 20
> };
js> for(var prop in obj) {
> print(prop + ': ' + obj[prop])
> }
x: 10
y: 20
js>
> x : 10,
> y : 20
> };
js> for(var prop in obj) {
> print(prop + ': ' + obj[prop])
> }
x: 10
y: 20
js>
使用[]運算子的場合之一,就是當你的特性會包括空白、. 字元等時。例如:
js> var obj = {
> 'caterpillar.onlyfun' : 'Openhome'
> };
js> obj.caterpillar.onlyfun;
js: "<stdin>", line 136: uncaught JavaScript runtime exception: TypeError: Cannot read property "onlyfun" from undefined
at <stdin>:136
js> obj['caterpillar.onlyfun'];
Openhome
js> delete obj['caterpillar.onlyfun'];
true
js> 'caterpillar.onlyfun' in obj;
false
js>
> 'caterpillar.onlyfun' : 'Openhome'
> };
js> obj.caterpillar.onlyfun;
js: "<stdin>", line 136: uncaught JavaScript runtime exception: TypeError: Cannot read property "onlyfun" from undefined
at <stdin>:136
js> obj['caterpillar.onlyfun'];
Openhome
js> delete obj['caterpillar.onlyfun'];
true
js> 'caterpillar.onlyfun' in obj;
false
js>
除了使用in測試物件上是否存在特性之外,由於物件上不存在某個特性時,你試圖存取時會傳回undefined,而undefined若在判斷是否成立時會被當作false,所以就有了特性偵測的作法:
js> var obj = {};
js> if(obj.x) {
> print('x exists.' );
> }
js> obj.x = 10;
10
js> if(obj.x) {
> print('x exists.' );
> }
x exists.
js>
js> if(obj.x) {
> print('x exists.' );
> }
js> obj.x = 10;
10
js> if(obj.x) {
> print('x exists.' );
> }
x exists.
js>
特性偵測也可以與||一同結合,用在合併物件特性。例如:
js> var obj = {
> x : 10,
> y : 20
> };
js> var option = {
> x : obj.x || 1,
> y : obj.y || 2,
> z : obj.z || 3
> };
js> option.x;
10
js> option.y;
20
js> option.z;
3
js>
> x : 10,
> y : 20
> };
js> var option = {
> x : obj.x || 1,
> y : obj.y || 2,
> z : obj.z || 3
> };
js> option.x;
10
js> option.y;
20
js> option.z;
3
js>
在上例中,選項物件的x、y、z特性預設值分別是1、2、3,如果obj上有提供對應的特性,則以obj提供的為主,否則就以選項物件的為主,這也經常用在函式上有太多參數及預設值要提供的場合,之後說明函式時還會看到(不清楚||運算為何會有這種結果的話,請看 運算子 中的說明)。
JavaScript是個弱型別語言,在需要將物件轉為數值的場合,會呼叫valueOf()方法。例如:
js> var obj = {
> valueOf : function() {
> return 100;
> }
> };
js> 100 + obj;
200
js> obj + 200;
300
js> obj > 100;
false
js> obj >= 100;
true
js>
> valueOf : function() {
> return 100;
> }
> };
js> 100 + obj;
200
js> obj + 200;
300
js> obj > 100;
false
js> obj >= 100;
true
js>
在需要將物件轉換為字串的場合,則會呼叫toString()方法。例如:
js> var caterpillar = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> toString : function() {
> return '[name: ' + this.name + ', url: ' + this.url + ']';
> }
> };
js> caterpillar;
[name: Justin Lin, url: openhome.cc]
js> 'My info: ' + caterpillar;
My info: [name: Justin Lin, url: openhome.cc]
js>
> name : 'Justin Lin',
> url : 'openhome.cc',
> toString : function() {
> return '[name: ' + this.name + ', url: ' + this.url + ']';
> }
> };
js> caterpillar;
[name: Justin Lin, url: openhome.cc]
js> 'My info: ' + caterpillar;
My info: [name: Justin Lin, url: openhome.cc]
js>
在上例中,this代表caterpillar所參考的物件,之後還會詳細說明this是什麼。
在JavaScript中,==或===用在物件比較時,是比較參考的對象是否為同一物件,而不是物件實際內含值,如果你要比較兩個物件實際上是否為同一物件,必須自行定義專屬方法,這個方法名稱並沒有規範。例如,也許定義個equals()方法:
js> var man1 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : function(other) {
> return (this.name == other.name) && (this.url == other.url);
> }
> };
js> var man2 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : function(other) {
> return (this.name == other.name) && (this.url == other.url);
> }
> };
js> man1 == man2;
false
js> man1 === man2;
false
js> man1.equals(man2);
true
js>
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : function(other) {
> return (this.name == other.name) && (this.url == other.url);
> }
> };
js> var man2 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : function(other) {
> return (this.name == other.name) && (this.url == other.url);
> }
> };
js> man1 == man2;
false
js> man1 === man2;
false
js> man1.equals(man2);
true
js>
在上例中,equals所參考的函式其實內容重複了。如果你懂在JavaScript中函式是物件的觀念,則可以修改如下:
js> function equals(other) {
> return (this.name == other.name) && (this.url == other.url);
> }
js> var man1 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : equals
> };
js> var man2 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : equals
> };
js> var man3 = {
> name : 'caterpillar',
> url : 'caterpillar.onlyfun.net',
> equals : equals
> };
js> man1.equals(man2);
true
js> man1.equals(man3);
false
js>
> return (this.name == other.name) && (this.url == other.url);
> }
js> var man1 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : equals
> };
js> var man2 = {
> name : 'Justin Lin',
> url : 'openhome.cc',
> equals : equals
> };
js> var man3 = {
> name : 'caterpillar',
> url : 'caterpillar.onlyfun.net',
> equals : equals
> };
js> man1.equals(man2);
true
js> man1.equals(man3);
false
js>
關於函式之後還會詳加說明。