js中的對(duì)象理解和使用起來(lái)都很簡(jiǎn)單,并且很頻繁的使用兑宇。但是碍侦,總有細(xì)節(jié),是我們可能會(huì)忽略的隶糕、或者是拿捏不定的
參考鏈接:http://javascript.ruanyifeng.com/grammar/object.html
1. 概述#
1.1對(duì)象的含義
所謂對(duì)象瓷产,就是一種無(wú)序的數(shù)據(jù)集合,由若干個(gè)“鍵值對(duì)”(key-value)構(gòu)成枚驻。
對(duì)象的生成方法测秸,通常有三種方法:
var o1 = {};
var o2 = new Object();
var o3 = Object.create(null);
1.2 對(duì)象的引用
如果不同的變量名指向同一個(gè)對(duì)象,那么它們都是這個(gè)對(duì)象的引用,也就是說(shuō)指向同一個(gè)內(nèi)存地址。修改其中一個(gè)變量贷岸,會(huì)影響到其他所有變量。
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
此時(shí)螟蒸,如果取消某一個(gè)變量對(duì)于原對(duì)象的引用七嫌,不會(huì)影響到另一個(gè)變量。
var o1 = {};
var o2 = o1;
o1 = 1;
o2 // {}
但是,這種引用只局限于<code>對(duì)象</code>惹资,對(duì)于原始類(lèi)型的數(shù)據(jù)則是<code>傳值引用</code>猴誊,也就是說(shuō)翅娶,都是值的拷貝党觅。
var x = 1;
var y = x;
x = 2;
y // 1
1.3 表達(dá)式還是語(yǔ)句區(qū)別
對(duì)象采用大括號(hào)表示卫漫,這導(dǎo)致了一個(gè)問(wèn)題:如果行首是一個(gè)大括號(hào)宏悦,它到底是表達(dá)式還是語(yǔ)句?
{ foo: 123 }
JavaScript引擎讀到上面這行代碼砖瞧,會(huì)發(fā)現(xiàn)可能有兩種含義。第一種可能是褂乍,這是一個(gè)表達(dá)式,表示一個(gè)包含foo屬性的對(duì)象;第二種可能是,這是一個(gè)語(yǔ)句僻澎,表示一個(gè)代碼區(qū)塊逗堵,里面有一個(gè)標(biāo)簽foo汁咏,指向表達(dá)式123。
為了避免這種歧義厚掷,JavaScript規(guī)定勤哗,如果行首是<b>大括號(hào)</b>,一律解釋為語(yǔ)句(<b>即代碼塊</b>)。如果要解釋為表達(dá)式(<b>即對(duì)象</b>)笑诅,必須在大括號(hào)前加上<b>圓括號(hào)</b>。
這種差異在eval語(yǔ)句中反映得最明顯:
eval('{foo: 123}') // 123
eval('({foo: 123})') // {foo: 123}
2. 相關(guān)操作#
2.1 查看所有key
var o = { key1: 1, key2: 2};
Object.keys(o);// ['key1', 'key2']
2.2 刪除屬性
delet命令用于刪除對(duì)象的屬性疮鲫,刪除成功后返回true吆你。
var o = {p: 1};
Object.keys(o) // ["p"]
delete o.p // true
o.p // undefined
Object.keys(o) // []
注意,刪除一個(gè)不存在的屬性俊犯,delete不報(bào)錯(cuò)妇多,而且返回true。
var o = {};
delete o.p // true
因此燕侠,不能根據(jù)delete命令的結(jié)果者祖,認(rèn)定某個(gè)屬性是存在的。
var o = Object.defineProperty({}, 'p', { value: 123, configurable: false});
o.p // 123
delete o.p // false
<code>delete命令只能刪除對(duì)象本身的屬性!!!</code>
2.3 in運(yùn)算符
in運(yùn)算符用于檢查對(duì)象是否包含某個(gè)屬性(注意贬循,檢查的是鍵名咸包,不是鍵值),如果包含就返回true杖虾,否則返回false。in運(yùn)算符的一個(gè)問(wèn)題是媒熊,它不能識(shí)別對(duì)象<i>繼承</i>的屬性奇适。
var o = new Object();
o.hasOwnProperty('toString') // false
'toString' in o // true
使用for in遍歷對(duì)象
var o = {a: 1, b: 2, c: 3};
for (var i in o) {
console.log(o[i]);
}
//提取對(duì)象屬性
var obj = { x: 1, y: 2};
var props = [];
var i = 0;
for (props[i++] in obj);
props // ['x', 'y']
2.4 with語(yǔ)句
(1)它的作用是操作同一個(gè)對(duì)象的多個(gè)屬性時(shí)坟比,提供一些書(shū)寫(xiě)的方便。
// 例一
with (o) {
p1 = 1;
p2 = 2;
}
// 等同于
o.p1 = 1;
o.p2 = 2;
// 例二
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);
注意嚷往,with區(qū)塊內(nèi)部的變量葛账,必須是當(dāng)前對(duì)象已經(jīng)存在的屬性,否則會(huì)創(chuàng)造一個(gè)當(dāng)前作用域的全局變量皮仁。這是因?yàn)閣ith區(qū)塊沒(méi)有改變作用域籍琳,它的內(nèi)部依然是當(dāng)前作用域。
var o = {};
with (o) {
x = "abc";
}
o.x // undefined
x // "abc"
(2)這是with語(yǔ)句的一個(gè)很大的弊病贷祈,就是綁定對(duì)象不明確趋急。
with (o) { console.log(x);}
單純從上面的代碼塊,根本無(wú)法判斷x到底是全局變量势誊,還是o對(duì)象的一個(gè)屬性呜达。這非常不利于代碼的除錯(cuò)和模塊化,編譯器也無(wú)法對(duì)這段代碼進(jìn)行優(yōu)化粟耻,只能留到運(yùn)行時(shí)判斷查近,這就拖慢了運(yùn)行速度。因此挤忙,建議不要使用with
語(yǔ)句霜威,可以考慮用一個(gè)<code>臨時(shí)變量</code>代替with。
with(o1.o2.o3) { console.log(p1 + p2);}
// 可以寫(xiě)成
var temp = o1.o2.o3;console.log(temp.p1 + temp.p2);
(3)with語(yǔ)句少數(shù)有用場(chǎng)合之一册烈,就是替換模板變量戈泼。