ECMAScript 中有兩種數(shù)據(jù)屬性,分別是數(shù)據(jù)屬性和訪問器屬性,下面來依次介紹。
1. 數(shù)據(jù)屬性
數(shù)據(jù)屬性有四個(gè)特性:
configurable: 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性改為訪問器屬性。enumerable: 表示能否for-in循環(huán)返回屬性。writable: 表示能否修改屬性的值。value: 包含這個(gè)屬性的值。
需要注意的是,當(dāng)我們使用不同的方式定義屬性的時(shí)候,上述四個(gè)特性的默認(rèn)值使不同的。比如對于下面這段代碼
var person = {
"age": "18"
};
var descriptor = Object.getOwnPropertyDescriptor(person, "age");
console.log(descriptor);
瀏覽器打印出如下信息 :
Object
configurable:true
enumerable:true
value:"18"
writable:true
這就說明,以上面這種方式定義屬性的時(shí)候,configurable, enumerable, writable 的默認(rèn)值將會是 true。
而定義屬性的方式還有另一種方法,那就是 defineProperty() 方法,這個(gè)方法定義的屬性 configurable, enumerable, writable 的默認(rèn)值將會使 false 。
var person = {};
Object.defineProperty(person, "age", {
value: "22"
});
var descriptor = Object.getOwnPropertyDescriptor(person, "age");
console.log(descriptor);
瀏覽器打印的消息如下 :
Object
configurable:false
enumerable:false
value:"22"
writable:false
當(dāng)然,如果我們不滿足默認(rèn)值,在定義的屬性的時(shí)候可以自己設(shè)置,比如我們將 enumerable 設(shè)置為 true。
Object.defineProperty(person, "age", {
enumerable: true,
value: "22"
});
2. 訪問器屬性
訪問器特性與數(shù)據(jù)屬性的不同之處是,它并沒有 value 特性, 而是多了一對 setter 和 getter 函數(shù)。下面來介紹訪問器的四個(gè)特性。
configurable: 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性改為訪問器屬性。enumerable: 表示能否for-in循環(huán)返回屬性。get: 讀取屬性時(shí)調(diào)用的函數(shù)。set: 寫入屬性時(shí)調(diào)用的函數(shù)。
訪問器的屬性不可以直接定義,需要借助于 defineProperty(),比如我們?yōu)?person 設(shè)置一個(gè) name 訪問器屬性。
var person = {
_name: "hwaphon"
};
Object.defineProperty(person, "name", {
get: function() {
return this._name;
},
set: function(value) {
if (typeof value === "string") {
this._name = value;
}
}
});
注意,_name 屬性中的 _ 其實(shí)是一種標(biāo)記,用于表示這個(gè)屬性只能通過對象方法獲得。其實(shí)只要你調(diào)用 person._name 仍然能獲取它的值,所以我感覺使用 _ 像是一種約定。
為什么要使用 set 和 get 呢?是為了對數(shù)據(jù)進(jìn)行驗(yàn)證,比如我們在設(shè)置年齡的時(shí)候,可以檢測輸入值是否為數(shù)字以及是否在合理范圍內(nèi)。
var person = {
_age: 12
};
Object.defineProperty(person, "age", {
get: function() {
return this._name;
},
set: function(newAge) {
if (typeof newAge === "number" && newAge > 0 && newAge <= 150) {
this._age = newAge;
} else {
console.log("not match!");
}
}
});
當(dāng)一個(gè)訪問器屬性只設(shè)置了 set 函數(shù)時(shí),由于沒有 get 函數(shù),所以這個(gè)屬性是不可讀的。
當(dāng)一個(gè)訪問器屬性只設(shè)置了 get 函數(shù)時(shí),由于沒有 set 函數(shù),所以這個(gè)屬性使不可寫入的。
還有一點(diǎn)值得注意,由于 Objcet.defineProperty() 是 ECMAScript 5 中才出現(xiàn)的,那么在不支持這個(gè)方法的瀏覽器中,該怎么定義 get 和 set 呢?可以借助于兩個(gè)非標(biāo)準(zhǔn)的方法, __defineGetter__() 和 __defineSetter__()。
var person = {
_age: 12
};
person.__defineGetter__("age", function() {
return this._age;
});
person.__defineSetter__("age", function(newAge) {
if (typeof newAge == "number") {
this._age = newAge;
}
});
提示: 方法中使用的是雙下劃線!