對(duì)象屬性
創(chuàng)建 JavaScript 自定義對(duì)象有兩種方法。一種是通過(guò) new 關(guān)鍵字創(chuàng)建一個(gè) Object 實(shí)例蔬蕊,然后為它添加屬性和方法租悄。
let person = new Object();
person.name = 'Zhang san';
person.age = 18;
person.job = 'Engineer';
person.sayName = function() {
alert(this.name);
};
另一種是對(duì)象的字面量嫡丙,也是創(chuàng)建對(duì)象首選的方式,前面的例子可以寫(xiě)成:
const person = {
name: 'Zhang san',
age: 18,
job: 'Engineer',
sayName: function() {
alert(this.name);
}
};
兩中方式的 person 對(duì)象是一樣的快鱼,有相同的屬性和方法颠印。這些屬性創(chuàng)建時(shí)都帶有默認(rèn)的特征,JavaScript 通過(guò)這些特征來(lái)定義對(duì)象的行為抹竹。
屬性的類型
數(shù)據(jù)屬性(Data property)
數(shù)據(jù)屬性表示存儲(chǔ)數(shù)據(jù)的位置线罕,在這個(gè)位置可以讀取和寫(xiě)入值。
數(shù)據(jù)屬性有 4 個(gè)描述其行為的特性:
- [[Configurable]]: 表示能夠通過(guò) delete 刪除屬性窃判,能夠修改屬性的特性钞楼,能夠修改訪問(wèn)屬性,直接在對(duì)象上定義屬性袄琳,默認(rèn)值為 true询件。
- [[Enumerable]]: 表示能否通過(guò) for-in 循環(huán)返回屬性值。直接在對(duì)象上定義屬性唆樊,默認(rèn)值 true.
- [[Writable]]: 表示能否修改屬性值宛琅。直接在對(duì)象上定義屬性,默認(rèn)值 true逗旁。
var person = ();
Object.defineProperty(person, "name", {
configurable: false,
wriable: false,
value: 'Zhang san'
}
delete person.name;
console.log(person.name); // Zhang san, 刪除無(wú)效
// TypeError: Cannot redefine property: name
Object.defineProperty(person, "name", {
configurable: false,
}
把 configuration
設(shè)置為 false
嘿辟,表示無(wú)法刪除該屬性,如果嘗試 delete
該屬性片效,則在非嚴(yán)格模式下什么都不會(huì)發(fā)生红伦。
對(duì)于已經(jīng)定義為不可配置的屬性,不能再通過(guò) Object
的 defineProperty
方法修改描述特性淀衣。強(qiáng)制修改會(huì)出現(xiàn)錯(cuò)誤:TypeError: Cannot redefine property: name
昙读。
訪問(wèn)器屬性(Accessor property)
訪問(wèn)器屬性不包含數(shù)據(jù)值,它包含一對(duì) getter 和 setter 函數(shù)舌缤,不過(guò)這兩個(gè)函數(shù)并不是必須的箕戳。
在讀取訪問(wèn)器屬性時(shí),會(huì)調(diào)用 getter 函數(shù)国撵,這個(gè)函數(shù)負(fù)責(zé)返回有效的值陵吸;在寫(xiě)入訪問(wèn)器屬性時(shí),會(huì)調(diào)用 setter 函數(shù)并傳入新值介牙,這個(gè)函數(shù)負(fù)責(zé)決定如何處理數(shù)據(jù)壮虫。
訪問(wèn)器屬性有如下 4 個(gè)特性:
- [[Configurable]]: 表示能否通過(guò) delete 刪除屬性重定義屬性,能否修改屬性的特性,或者能否把屬性修改為數(shù)據(jù)屬性囚似。直接在對(duì)象上定義屬性剩拢,默認(rèn)值為 true。
- [[Enumerable]]: 表示能夠通過(guò) for-in 循環(huán)返回屬性饶唤,直接在對(duì)象上定義屬性徐伐,默認(rèn)值 true。
- [[Get]]: 在讀取函數(shù)時(shí)調(diào)用的函數(shù)募狂。默認(rèn)值是 undefined办素。
- [[Set]]: 在寫(xiě)入屬性時(shí)調(diào)用的函數(shù)。默認(rèn)值 undefined祸穷。
var book = {
_year: 2018,
edition: 1
}
Object.defineProperty(book, 'year', {
get() {
return this._year;
},
set(newValue) {
if (newValue > 2018) {
this._year = newValue;
this.edition += newValue - 2018;
}
}
});
book.year = 2020;
console.log(book.edition); // 3
這里的
_year
可以理解為 Swift 中的 stored properties性穿,year
類似于 computed properties。
定義多個(gè)屬性
如果有多個(gè)屬性需要定義特性雷滚,用 defineProperty
逐個(gè)定義有些繁瑣需曾。ECMAScript5 又定義了一個(gè) Object.defineProperties()
方法。利用這個(gè)方法可以通過(guò)描述符一次定義多個(gè)屬性祈远。
這個(gè)方法接受兩個(gè)對(duì)象參數(shù):第一個(gè)對(duì)象是要添加和修改其屬性的對(duì)象呆万,第二個(gè)對(duì)象的屬性與第一個(gè)對(duì)象中要添加或者修改的屬性一一對(duì)應(yīng)。
例如:
var book = {};
Object.defineProperties(book, {
_year: {
writable: true,
value: 2018
},
edition: {
configurable: true,
writable: true,
value: 1
},
year: {
get() {
return this._year;
},
set(newValue) {
this._year = newValue;
this.edition += newValue - 2018;
}
}
});
book.year = 2020;
console.log(book.edition);
以上方法在 book 對(duì)象上定義了兩個(gè)數(shù)據(jù)屬性和一個(gè)訪問(wèn)器屬性绊含。
讀取屬性的特性
使用Object.getOwnPropertyDescriptor()
方法桑嘶,可以取得給定屬性的描述符。這個(gè)方法接收兩個(gè)參數(shù):屬性所在的對(duì)象和讀取其描述符的屬性名稱躬充。
返回值是一個(gè)對(duì)象逃顶,如果是訪問(wèn)器屬性,這個(gè)對(duì)象的屬性是 configurable充甚、enumerable以政、get、set伴找;如果是數(shù)據(jù)屬性盈蛮,這個(gè)對(duì)象的屬性有 configurable、enumerable技矮、writable 和 value抖誉。
// 訪問(wèn)器屬性
var descriptor = Object.getOwnPropertyDescriptor(book, 'year');
console.log(descriptor);
/**
{
get: [Function: get],
set: [Function: set],
enumerable: false,
configurable: false
}
*/
// 數(shù)據(jù)屬性
var descriptor1 = Object.getOwnPropertyDescriptor(book, 'edition');
console.log(descriptor1);
/**
{
value: 3,
writable: true,
enumerable: false,
configurable: true
}
*/
總結(jié)
屬性的描述符一般會(huì)有以下幾種用途:
- 檢查某個(gè)屬性能夠通過(guò) for-in 從對(duì)象中枚舉;
- 檢查對(duì)象的某個(gè)屬性能否修改衰倦;
- 屬性觀察袒炉,在屬性改變時(shí)做副作用操作。
微信公眾號(hào) iOSTalk