Object 對象屬性的操作


屬性查詢
屬性查詢一般有兩種方法,包括點運算符和方括號運算符:

var o = {
  p: 'Hello World'
};
o.p // "Hello World"
o['p'] // "Hello World"
1➢ 點運算
點運算符是很多面向對象語句的通用寫法,由於其比較簡單,所以較方括號運算符相比,更常用。

當通過點運算符訪問對象的屬性時,屬性名用一個標識符來表示,標識符必須要符合變量命名規則。

標識符必須直接出現在javascript程序中,它們不是數據類型,因此程序無法修改它們。

var o = {
    a:1,
    1:2
};
console.log(o.a);//1
//由於變量不可以以數字開頭,所以o.1報錯
console.log(o.1);//Uncaught SyntaxError: missing ) after argument list
2➢ 方括號運算
當通過方括號運算符來訪問對象的屬性時,屬性名最終通過字符串來表示。字符串是javascript的數據類型,在程序運行中可以修改和創建它們。

使用方括號運算符有兩個優點。

【一】可以通過變量來訪問屬性

var a = 1;
var o = {
    1: 10
}
o[a];//10
【二】屬性名稱可以為 javascript無效標識符(即,不符合變量命名規則)

var myObject = {
    123:'zero',
    class:'foo'
};
console.log(myObject['123'],myObject['class']);//'zero' 'foo'
console.log(myObject.123);//報錯
2.1➢ 判斷調用String()隱式轉換
【1】方括號中的值若是 字符串類型(外面有引號),就會正常按字符串訪問對象的屬性;

【2】方括號中的值若是 非字符串類型(外面沒有引號),就會先判斷是否符合變量命名規則,

【2-1】如果不符合,就會底層調用String()隱式轉換成字符串再交由方括號運算;

【2-2】如果符合,就是變量了,被當作通過變量來訪問屬性的情況(這個時候,如果對應變量沒有定義,當然就會報錯)。

2.1.1➢ 看demo我們就很容易理解:
var myObject = {
    123:'this is 123',
    clasz:'this is clasz'
};
console.log(myObject["123"]) // 正常訪問'this is 123'
console.log(myObject["clasz"]) // 正常訪問'this is clasz'
console.log(myObject[123]) // 123隱式轉換成字符串"123",訪問得到'this is 123'
console.log(myObject[clasz]) // clasz符合變量命名規則,被當作變量:Error: clasz is not defined
2.1.2➢ 再細看【2-2】:
var myObject = {
    123:'this is 123',
    clasz:'this is clasz',
    extra: 'this is 補充'
};
console.log(myObject[clasz]) // clasz符合變量命名規則,被當作變量:Error: clasz is not defined
對比:

var myObject = {
    123:'this is 123',
    clasz:'this is clasz',
    extra: 'this is 補充'
};
var clasz = "extra"
console.log(myObject["clasz"]) // 訪問得到'this is 補充'
現在我們就能理解為什么【2】要這么設置了。

2.2➢ 可計算屬性名
在方括號運算符內部可以使用表達式:

var a = 1;
var person = {
    3: 'abc'
};
person[a + 2];//'abc'
但如果要在對象字面量內部對屬性名使用表達式,則需要使用ES6的可計算屬性名:

var a = 1;
//Uncaught SyntaxError: Unexpected token +
var person = {
    a + 3: 'abc'
};
ES6增加了可計算屬性名,可以在文字中使用[]包裹一個表達式來當作屬性名:

var a = 1;
var person = {
    [a + 3]: 'abc'
};
person[4];//'abc'
3➢ 屬性查詢錯誤
【1】查詢一個不存在的屬性不會報錯,而是返回undefined:

var person = {};
console.log(person.a);//undefined
【2】如果對象不存在,試圖查詢這個不存在的對象的屬性會報錯:

console.log(person.a);//Uncaught ReferenceError: person is not defined
可以利用這一點,來檢查一個全局變量是否被聲明:

// 檢查a變量是否被聲明
if (a) {...} // 報錯
//-----------------------------------------//
//所有全局變量都是window對象的屬性。window.a的含義就是讀取window對象的a屬性,如果該屬性不存在,就返回undefined,並不會報錯
if (window.a) {...} // 不報錯
屬性設置
屬性設置又稱為屬性賦值,與屬性查詢相同,具有點運算符和方括號運算符這兩種方法。

在給對象設置屬性之前,一般要先檢測對象是否存在:

var len = undefined;
if(book){
    if(book.subtitle){
        len = book.subtitle.length;
    }
}
上面代碼可以簡化為:

var len = book && book.subtitle && book.subtitle.length;
1➢ 屬性設置錯誤
null和undefined不是對象,給它們設置屬性會報錯:

null.a = 1;//Uncaught TypeError: Cannot set property 'a' of null
undefined.a = 1;//Uncaught TypeError: Cannot set property 'a' of undefined
由於string、number和boolean有對應的 包裝對象 ,所以給它們設置屬性不會報錯:

'abc'.a = 1;//1
(1).a = 1;//1
true.a = 1;//1
屬性刪除
使用delete運算符可以刪除對象屬性(包括數組元素):

var o = {
    a : 1
};
console.log(o.a);//1
console.log('a' in o);//true
console.log(delete o.a);//true
console.log(o.a);//undefined
console.log('a' in o);//false
而如果給對象屬性置null或undefined,其實並沒有刪除該屬性:

var o = {
    a : 1
};
o.a = undefined;
console.log(o.a);//undefined
console.log('a' in o);//true
console.log(delete o.a);//true
console.log(o.a);//undefined
console.log('a' in o);//false
使用delete刪除數組元素時,不會改變數組長度:

var a = [1,2,3];
delete a[2];
2 in a;//false
a.length;//3
delete運算符只能刪除自有屬性,不能刪除繼承屬性(要刪除繼承屬性必須從定義這個屬性的原型對象上刪除它,而且這會影響到所有繼承自這個原型的對象)

var o  = {
    a:1
}
var obj = Object.create(o);
obj.a = 2;
console.log(obj.a);//2
console.log(delete obj.a);//true
console.log(obj.a);//1
console.log(delete obj.a);//true
console.log(obj.a);//1
1➢ 返回值
delete操作符的返回值是個布爾值true或false

【1】當使用delete操作符刪除對象屬性或數組元素刪除成功時,返回true

var o = {a:1};
var arr = [1];
console.log(delete o.a);//true
console.log(delete arr[0]);//true
【2】當使用delete操作符刪除 不存在的屬性 或 非左值 時,返回true

var o = {};
console.log(delete o.a);//true
console.log(delete 1);//true
console.log(delete {});//true
【3】當使用delete操作符刪除變量時,返回false,嚴格模式下會拋出ReferenceError錯誤

var a = 1;
console.log(delete a);//false
console.log(a);//1
'use strict';
var a = 1;
//Uncaught SyntaxError: Delete of an unqualified identifier in strict mode
console.log(delete a);
【4】當使用delete操作符刪除不可配置的屬性時,返回false,嚴格模式下會拋出TypeError錯誤

var obj = {};
Object.defineProperty(obj,'a',{configurable:false});
console.log(delete obj.a);//false
'use strict';
var obj = {};
Object.defineProperty(obj,'a',{configurable:false});
//Uncaught TypeError: Cannot delete property 'a' of #<Object>
console.log(delete obj.a);
屬性繼承
每一個javascript對象都和另一個對象相關聯。“另一個對象”就是我們熟知的原型,每一個對象都從原型繼承屬性。

對象本身具有的屬性叫自有屬性(own property),從原型對象繼承而來的屬性叫繼承屬性:

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
//繼承自原型對象o的屬性a
console.log(obj.a);//1
//自有屬性b
console.log(obj.b);//2
1➢ hasOwnProperty()
通過hasOwnProperty()方法可以確定該屬性是自有屬性還是繼承屬性

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
console.log(obj.hasOwnProperty('a'));//false
console.log(obj.hasOwnProperty('b'));//true
2➢ in
in操作符可以判斷屬性在不在該對象上,但無法區別自有還是繼承屬性:

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
console.log('a' in obj);//true
console.log('b' in obj);//true
console.log('b' in o);//false
3➢ for-in
通過for-in循環可以遍歷出該對象中所有可枚舉屬性:

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
for(var i in obj){
    console.log(obj[i]);//2 1
}
4➢ Object.keys()
Object.keys()方法返回所有可枚舉的自有屬性:

var o = {a:1};
var obj = Object.create(o,{
    c:{value:3,configurable: false}
});
obj.b = 2;
console.log(Object.keys(obj));//['b']
5➢ Object.getOwnPropertyNames()
與Object.keys()方法不同,Object.getOwnPropertyNames()方法返回所有自有屬性(包括不可枚舉的屬性)

var o = {a:1};
var obj = Object.create(o,{
    c:{value:3,configurable: false}
});
obj.b = 2;
console.log(Object.getOwnPropertyNames(obj));//['c','b']

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。