属性描述符在ES5开始,所有属性都具备了属性描述符。我们可以通过Object.getOwnPropertyDescriptor来观察到属性的描述符,它是长这样子的。Object.getOwnPropertyDescriptor({a: 1}, ‘a’);// {// value: 1,// writable: true,// enumerable: true,// configurable: true// }writable决定该属性是否只读。enumerable决定该属性是否可枚举。configurable决定该属性是否可重新设置描述符。属性描述符的设置当属性的configurable为true时,我们可以通过Object.defineProperty来修改属性描述符。‘use strict’;var foo = {a: 1};for(var i in foo) {console.log(i)};// ‘a’Object.defineProperty(foo, ‘a’, { writable: false, enumerable: false, configurable: false});foo.a = 2;// Uncaught TypeError: Cannot assign to read only property ‘a’ of object ‘#<Object>‘for(var i in foo) {console.log(i)};// ’nothing happend’Object.defineProperty(foo, ‘a’, { // Uncaught TypeError: Cannot redefine property: a configurable: true});访问描述符(getter和setter)getter和setter有两种方式定义字面量定义var foo = { get a(){ return this._a; }, set a(value){ this._a = value; }};使用Object.defineProperty定义var foo = {a: 1};Object.defineProperty( foo, ‘a’, { get(){ return this._a; }, set(value){ this._a = value; } });这个时候再看看属性a的描述符。Object.getOwnPropertyDescriptor(foo, ‘a’)// {// get: ƒ a(),// set: ƒ a(value),// enumerable: true,// configurable: true// }当出现getter或setter时,value和writable就会失效。此时,属性a的描述符被称为访问描述符。访问描述符和属性描述符互斥,如果此时再重新设置value或者writable描述符,setter和getter也会被丢弃。屏蔽属性当你给一个对象赋值一个新的属性foo时,如果该对象的原型链上已存在属性foo,并且foo被标记为只读(writable: false)时,严格模式下会抛出异常,非严格模式下,这条赋值语句会被忽略。这种属性称为屏蔽属性。举个例子’use strict’;var anotherObject = {};Object.defineProperty(anotherObject, ‘foo’, {// 将anotherObject的foo属性设为只读 value: 1, writable: false});var myObject = Object.create(anotherObject);// 将myObject的原型设置为anotherObjectconsole.log(myObject);// {}console.log(myObject.foo);// 1myObject.foo = 2;// Uncaught TypeError: Cannot assign to read only property ‘a’ of object ‘#<Object>‘还有一种情况当你给一个对象赋值一个新的属性foo时,如果该对象的原型链上已存在属性foo,并且foo被设置了setter时,将会调用这个setter,并且该赋值语句将会被忽略,此时也会发生属性屏蔽。var anotherObject = {};Object.defineProperty(anotherObject, ‘foo’, {// 给anotherObject的foo属性设置setter set(value) { console.log(value); this._foo = value; }, get() { return this._foo; }});var myObject = Object.create(anotherObject);// 将myObject的原型设置为anotherObjectmyObject.foo = 2;// 此时会触发anotherObject.foo的setter,控制台输出2console.log(Object.hasOwnProperty(myObject, ‘foo’));// false解决方案使用Object.defineProperty来添加属性。
属性描述符
December 21, 2018 · 1 min · jiezi