ES5的Object中有一个方法:Object.defineProperty,这个方法能够直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象(摘自MDN)。web
Object.defineProperty(obj, prop, descriptor)
复制代码
其中:bash
obj: (必需, Object) 即将在其上定义属性的目标对象
prop: (必需, String) 即将定义(或修改)的属性的名称
descriptor: (必需, Object) 即将被定义(或修改)的属性的描述符
复制代码
前两个参数好理解,主要是第三个参数比较麻烦。在分析第三个参数前,先举一个例子:函数
let Product = {};
Object.defineProperty(Product, "discount", {
// 对discount属性的描述
})
复制代码
在上面的代码中,我建立了一个Product对象,并为其添加了一个discount属性,而第三个参数则是对该属性的描述.ui
接下来咱们要详细分析一下descriptor参数,即属性的描述符。this
属性描述符能够有两种形式:数据描述符和存取描述符,这两种形式的键值有的相同,有的不一样,具体以下:spa
configurable
复制代码
当且仅当该属性的configurable为true时,该属性描述符才可以被改变,同时该属性也能从对应的对象上被删除。默认为false。code
enumerable
复制代码
当且仅当该属性的enumerable为true时,该属性才可以出如今对象的枚举属性中。默认为 false。cdn
value
复制代码
该属性对应的值。能够是任何有效的JavaScript值(数值,对象,函数等)。默认为undefined。对象
writable
复制代码
当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为false。blog
get
复制代码
一个给属性提供 getter 的方法,若是没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,可是会传入this对象(因为继承关系,这里的this并不必定是定义该属性的对象)。 默认为 undefined。
set
复制代码
一个给属性提供 setter 的方法,若是没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受惟一参数,即该属性新的参数值。 默认为 undefined。
综上,如今我能够经过数据描述符为对象添加一个属性:
let Product = {};
Object.defineProperty(Product, "discount", {
value: 20,
writable: true,
configurable: true,
enumerable: true
})
复制代码
也能够经过存取描述符为对象添加属性:
let Product = {},
value = 1;
Object.defineProperty(Product, "discount", {
get: function () {
return value;
},
set: function (newValue) {
value = newValue;
},
configurable: true,
enumerable: true
})
复制代码
此外,必定要注意:属性描述符能够是数据或存取描述符的其中一种,可是千万不能混用。好比这样:
let Product = {};
Object.defineProperty(Product, "discount", {
value: 20,
writable: true,
// get不能与value,writable同时使用!!
get: function () {
return 20;
},
configurable: true,
enumerable: true
})
复制代码
这是错误的!
IE8如下是不兼容的。
参考资料: