屬性描述符
我們定義的物件,對應的每一個屬性都對應一個‘屬性描述符’物件,用來描述該屬性的一些特性: 屬性描述符有兩種形式:資料描述符或存取描述符。資料描述符是一個具有值的屬性,該值可能是可寫的,也可能不是可寫的。存取描述符是由getter-setter函式對描述的屬性。屬性描述符必須是這兩種形式之一;且不能同時是兩者
- 資料描述符獨有的:
- value:改屬性的值
- writable:為true表示該屬性的value可以被重寫
- 存取描述符獨有的:
- get:獲取該屬性的訪問器函式(getter),當訪問該屬性時,該方法會被執行,方法執行時沒有引數傳入;如果沒有 getter 則為 undefined
- set:該屬性的設定器函式(setter),當屬性值修改時,觸發執行該方法。該方法將接受唯一引數,即該屬性新的引數值;如果沒有則為undefined,為該屬性賦不了值
- 資料描述符和存取描述符都含有的:
- configurable:為ture時,表示當前屬性的‘屬性表述符’物件可以被更改,該屬性可以使用delete刪除,否則就是不允許更改
- enumerable:為true時,表示當前屬性可以被列舉,也就是當前屬性是否可以在 for...in 迴圈和 Object.keys() 中被遍歷出來
- (value和writable)與(get和set)是不共存的,只要定義了其中一個,就定下來了該描述符的性質是資料描述符還是存取描述符
錯誤的案例:
var o = {}; Object.defineProperty(o, "a", { get : function(){return 1;},value : 12 } ); // Uncaught TypeError:Invalid property descriptor.Cannot both specify accessors and a value or writable attribute var o = {}; Object.defineProperty(o, "a", { get : function(){return 1;}, configurable : true } ); Object.defineProperty(o, "a", {value : 12}); // 這裡重寫了屬性描述符,將其變為資料描述符,且沒定義的configurable 不會重寫 console.log(o.a) // 12 d = Object.getOwnPropertyDescriptor(o, "a"); console.log(d) //{value: 20, writable: false, enumerable: false, configurable: true} 複製程式碼
Object.defineProperty(obj, prop, descriptor)建立或修改物件的單個屬性
用來定義或修改obj物件上prop屬性的descriptor屬性描述符
- obj:要在其上定義屬性的物件。
- prop:要定義或修改的屬性的名稱。
- descriptor:object,將被定義或修改的屬性描述符 當描述符中省略某些欄位時,這些欄位將使用它們的預設值。擁有布林值的欄位的預設值都是false。 value,get和set欄位的預設值為undefined。一個沒有get/set/value/writable定義的屬性被稱為“通用的”,並被“鍵入”為一個資料描述符
var bValue, o={};
Object.defineProperty(o, "b", {
set : function(newValue){
bValue = newValue;
},
enumerable : true,
configurable : true
});
console.log(o.b) //undefined 沒有顯示定義getter函式,因此預設值為undefined,所以使用o.b呼叫時為undefined
o.b= 11
console.log(bValue) // 11 給屬性賦值時,呼叫了setter函式,將值賦值給了bValue
複製程式碼
var o={};
Object.defineProperty(o, "b", {
get : function(){
return 22;
},
enumerable : true,
configurable : true
});
console.log(o.b) //22
o.b = 123
console.log(o.b) //22 因為沒有顯示定義setter,所以預設值為undefined,賦值動作無效,因此o.b不會變化
複製程式碼
Object.defineProperties(obj, props) 建立或修改物件的多個屬性
var Obj = {
"a":10
};
Object.defineProperties(Obj,{
"a1":{
get: function(){return this.a+1;},
set: function(val){ this.a = val;}
},
"a2":{
get: function(){return this.a+"test";},
set: function(val){this.b = val}
}
});
console.log(Obj.a1); //11
console.log(Obj.a2); //1test
Obj.a1 = 3;
Obj.a2 = 'hello';
console.log(Obj.a1); //4
console.log(Obj.a2); //3test
複製程式碼
修改屬性
- Writable 屬性 當writable屬性設定為false時,該屬性被稱為“不可寫”
var o = {}; // 建立一個新物件
// 在物件中新增一個屬性與資料描述符的示例
Object.defineProperty(o, "a", {
value : 37,
writable : false,
enumerable : true,
configurable : true
});
o.a = 123
console.log(o.a) //37 賦值無效
複製程式碼
- Enumerable 特性 enumerable定義了物件的屬性是否可以在 for...in 迴圈和 Object.keys() 中被列舉
var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable:true });
Object.defineProperty(o, "b", { value : 2, enumerable:false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable defaults to false
o.d = 4; // 如果使用直接賦值的方式建立物件的屬性,則這個屬性的enumerable為true
for (var i in o) {
console.log(i);
}
// 列印 'a' 和 'd' (in undefined order)
Object.keys(o); // ["a", "d"]
o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
複製程式碼
- Configurable 特性 configurable特性表示物件的屬性是否可以被刪除及屬性描述符是否可以被修改
var o = {};
Object.defineProperty(o, "a", {value : 12,
configurable : false } );
Object.defineProperty(o, "a", {value : 20}); // Uncaught TypeError: Cannot redefine property: a
delete o.a // false 刪除失敗
console.log(o.a) // 12 還是可以正常訪問
複製程式碼
我們熟悉的預設寫法
var o = {};
o.a = 1;
// 等同於 :
Object.defineProperty(o, "a", {
value : 1,
writable : true,
configurable : true,
enumerable : true
});
var o = { get foo() { return 17; } };
var p = Object.getOwnPropertyDescriptor(o, 'foo')
console.log(p)
// {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
// 另一方面,
Object.defineProperty(o, "a", { value : 1 });
// 等同於 :
Object.defineProperty(o, "a", {
value : 1,
writable : false,
configurable : false,
enumerable : false
});
複製程式碼
Object.getOwnPropertyDescriptor(obj, prop) 獲取指定物件自有屬性的屬性描述符
obj:需要查詢的目標物件 prop:目標物件內屬性名稱(String型別)
var o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
// configurable: true,
// enumerable: true,
// value: 42,
// writable: true
// }
o = {};
Object.defineProperty(o, "baz", {
value: 8675309,
writable: false,
enumerable: false
});
d = Object.getOwnPropertyDescriptor(o, "baz");
// d {
// value: 8675309,
// writable: false,
// enumerable: false,
// configurable: false
// }
複製程式碼