1. 语法
Object.defineProperty(obj, prop, descriptor)
- obj:要在其上定义属性的对象。
- prop:要定义或修改的属性的名称。
- descriptor:将被定义或修改的属性描述符。
- 返回值:被传递给函数的对象。
2. 属性描述符
- 创建属性
如果对象中不存在指定的属性,Object.defineProperty() 就创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值——拥有布尔值的字段的默认值都是false;value,get 和 set 字段的默认值为 undefined。一个没有get/set/value/writable定义的属性被称为“通用的”,并被“键入”为一个数据描述符。
- 修改属性
1. Writable:当 writable 属性设置为 false 时,该属性被称为“不可写”。它不能被重新分配。试图写入非可写属性不会改变它,也不会引发错误。
2. Enumerable:enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
3. Configurable:configurable 特性表示对象的属性是否可以被删除,以及除 writable 特性外的其他特性是否可以被修改。
添加多个属性和默认值
通常,使用点运算符和 Object.defineProperty() 为对象的属性赋值时,数据描述符中的属性默认值是不同的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21var o = {};
o.a = 1;
// 等同于 :
Object.defineProperty(o, "a", {
value : 1,
writable : true,
configurable : true,
enumerable : true
});
// 另一方面,
Object.defineProperty(o, "a", { value : 1 });
// 等同于 :
Object.defineProperty(o, "a", {
value : 1,
writable : false,
configurable : false,
enumerable : false
});一般的 Setter 和 Getter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this, 'temperature', {
get: function() {
console.log('get!');
return temperature;
},
set: function(value) {
temperature = value;
archive.push({ val: temperature });
}
});
this.getArchive = function() { return archive; };
}
var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
3. 重定义数组对象的 length 属性
数组的 length 属性是可以重定义的,但是会受到一般的重定义限制。(length 属性初始化为 non-configurable,non-enumerable,以及 writable。对于一个内容不可变的数组,改变其 length 属性的值或者使它变为 non-writable 是可以的。但是改变其可枚举性和可配置性或者当它是 non-writable 时尝试改变它的值或是可写性,这两者都是不被允许的。)然而,并不是所有浏览器都允许 Array.length 的重定义。只在 Internet Explorer 9 及以后版本和 Firefox 23 及以后版本中,才完整地正确地支持数组 length 属性的重新定义。
4. IE 8 具体案例
Internet Explorer 8 实现了 Object.defineProperty() 方法,但 只能在 DOM 对象上使用。 需要注意的一些事情:
- 尝试在原生对象上使用 Object.defineProperty() 会报错。
- 属性特性必须设置一些特定的值。对于数据属性描述符,configurable, enumerable 和 writable 特性必须全部设置为 true;对于访问器属性描述符,configurable 必须设置为 true,enumerable 必须设置为 false。试图提供其他值将导致一个错误抛出。
- 重新配置一个属性首先需要删除该属性。如果属性没有删除,就如同重新配置前的尝试。