前言:上一遍博客介紹了JS中的五種簡單數(shù)據(jù)類型盏求,這篇博客主要介紹JS中的復(fù)雜數(shù)據(jù)類型噪漾,object對象。注:本文參考阮一峰JS教程中關(guān)于對象的介紹蜂莉,然后結(jié)合自己的理解寫成蜡娶,附帶鏈接 。
1映穗、概述
什么是對象窖张?簡單說,對象就是一組“鍵值對”(key-value)的集合蚁滋,是一種無序的復(fù)合數(shù)據(jù)集合宿接。
對象的所有鍵名都是字符串(ES6 又引入了 Symbol 值也可以作為鍵值)赘淮,所以加不加引號都可以。如果鍵名是數(shù)值的時候睦霎,會被自動轉(zhuǎn)為字符串梢卸。所以“鍵名可以是數(shù)值”這句話是錯誤的。如下列代碼副女,看著鍵名是數(shù)值蛤高,但實際上它們已經(jīng)被轉(zhuǎn)換成字符串了。
var obj = {
1: 'a',
3.2: 'b',
1e2: true,
1e-2: true,
.234: true,
0xFF: true
};
但是肮塞,當鍵名不加引號的時候襟齿,則其必須符合標識名的條件(比如第一個字符不能為數(shù)字,或者不能含有空格或運算符)枕赵,且也不是數(shù)字猜欺,否則會報錯。
2拷窜、對象的引用
如果不同的變量名指向同一個對象开皿,那么它們都是這個對象的引用,也就是說指向同一個內(nèi)存地址篮昧。修改其中一個變量赋荆,會影響到其他所有變量。
如:
var o1 = {};"hello world"
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
上面代碼中懊昨,o1和o2指向同一個對象窄潭,因此為其中任何一個變量添加屬性,另一個變量都可以讀寫該屬性酵颁。
此時嫉你,如果取消某一個變量對于原對象的引用,不會影響到另一個變量躏惋。
var o1 = {};
var o2 = o1;
o1 = 1;
o2 // {}
注意:上述規(guī)律只適用于對象幽污,如果是變量的話,即兩個變量指向同一個原始類型的值簿姨。那么距误,變量這時都是值的拷貝。如:
var x = 1;
var y = x;
x = 2;
y // 1
3扁位、表達式還是語句准潭?
這么一行代碼,你覺得它是語句還是對象:{ foo: 123 }
域仇,很多人會說刑然,很顯然嘛,大括號里面的是一個"鍵值對"的形式殉簸,肯定表示對象闰集。
但是計算機沒有那么智能,JavaScript 引擎讀到上面這行代碼般卑,會發(fā)現(xiàn)可能有兩種含義武鲁。第一種可能是,這是一個表達式蝠检,表示一個包含foo屬性的對象沐鼠;第二種可能是,這是一個語句叹谁,表示一個代碼區(qū)塊饲梭,里面有一個標簽foo,指向表達式123焰檩。
為了避免這種歧義憔涉,JavaScript 規(guī)定,如果行首是大括號析苫,一律解釋為語句(即代碼塊)兜叨。如果要解釋為表達式(即對象),必須在大括號前加上圓括號衩侥。所以国旷,這句話{ foo: 123 }
JS會將其解讀成語句。
那么想表示對象該怎么寫呢茫死,舉個例子:
({ foo: 123})
4跪但、對象中屬性的讀取
讀取對象的屬性,有兩種方法峦萎,一種是使用點運算符屡久,如obj.p
,還有一種是使用方括號運算符骨杂,如obj['p']
涂身。很明顯,我們平常使用最多的方式還是點運算符搓蚪。不過還是有幾個坑容易踩(JS中總是有很多坑)蛤售,下面大致介紹一下兩種方法需要注意的地方。
- 如果使用方括號運算符妒潭,鍵名必須放在引號里面悴能,否則會被當作變量處理。
- 方括號運算符內(nèi)部還可以使用表達式雳灾。如
obj['hello' + ' world']
漠酿、
obj[3 + 3]
,獲取的是運算后的結(jié)果的屬性谎亩,比如obj[3 + 3]
獲取的是obj[6]
的屬性炒嘲,哪怕它其中有一個鍵名是'3+3'宇姚,也是獲取不到的,想要獲取鍵名是'3+3'的屬性 夫凸,得這么寫obj['3 + 3']
浑劳。 - 數(shù)字鍵可以不加引號,因為會自動轉(zhuǎn)成字符串夭拌。
- 數(shù)值鍵名不能使用點運算符(因為會被當成小數(shù)點)魔熏,只能使用方括號運算符。
- 想使用點運算符鸽扁,鍵名必須的符合標示符規(guī)范
所以很顯然蒜绽,雖然點運算符寫代碼是時候方便,但是也容易不小心踩到坑桶现,需要注意很多躲雅;方括號運算符不用考慮太多,只是寫起來稍微麻煩一點骡和,怎么取舍就要看官自己決定啦吏夯。
5、對象中屬性的賦值
點運算符和方括號運算符即横,不僅可以用來讀取值噪生,還可以用來賦值。
JavaScript 允許屬性的“后綁定”东囚,也就是說跺嗽,你可以在任意時刻新增屬性,沒必要在定義對象的時候页藻,就定義好屬性桨嫁。(具體原因參看第2條)
6、操作對象的幾種命令
- 查看一個對象本身的所有屬性份帐,可以使用
Object.keys
方法璃吧。舉例說明:
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
delete
命令用于刪除對象的屬性,刪除成功后返回true废境。需要注意的是:刪除一個不存在的屬性畜挨,delete不報錯,而且返回true噩凹。in
運算符用于檢查對象是否包含某個屬性(注意巴元,檢查的是鍵名,不是鍵值)驮宴,如果包含就返回true逮刨,否則返回false。舉例說明:
var obj = { p: 1 };
'p' in obj // true
-
for…in
循環(huán)堵泽,用來遍歷一個對象的全部屬性修己。舉個栗子:
var obj = {a: 1, b: 2, c: 3};
for (var i in obj) {
console.log(obj[i]);
}
// 1
// 2
// 3
當然恢总,使用for…in循環(huán)也可以便利對象的屬性名,即鍵值:
var obj = {
x: 1,
y: 2
};
var props = [];
var i = 0;
for (var p in obj) {
props[i++] = p
}
props // ['x', 'y']
不過使用for…in循環(huán)有以下兩點需要注意:
- 它遍歷的是對象所有可遍歷(enumerable)的屬性睬愤,會跳過不可遍歷的屬性离熏。
- 它不僅遍歷對象自身的屬性,還遍歷繼承的屬性戴涝。
-
with
語句,它的作用是操作同一個對象的多個屬性時钻蔑,提供一些書寫的方便啥刻。
舉個栗子:
with (document.links[0]){
console.log(href);
console.log(title);
console.log(style);
}
// 等同于
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);
注意1:如果with區(qū)塊內(nèi)部有變量的賦值操作,必須是當前對象已經(jīng)存在的屬性咪笑,否則會創(chuàng)造一個當前作用域的全局變量可帽。
注意 2:with語句的一個很大的弊病,就是綁定對象不明確窗怒。所以一般情況不建議使用with語句映跟。