可写性(writable)
可写性(writable)决定了属性的值(value)是否可以被改变。
var o = {};
Object.defineProperty(o, 'a', {
value: 37,
writable: false
});
o.a // 37
o.a = 25;
o.a // 37
上面代码将o对象的a属性可写性设为false,然后改变这个属性的值,就不会有任何效果。
注意,正常模式下,对可写性为false的属性赋值不会报错,只会默默失败。但是,严格模式下会报错,即使是对a属性重新赋予一个同样的值。
关于可写性,还有一种特殊情况。就是如果原型对象的某个属性的可写性为false,那么派生对象将无法自定义这个属性。
var proto = Object.defineProperty({}, 'foo', {
value: 'a',
writable: false
});
var o = Object.create(proto);
o.foo = 'b';
o.foo // 'a'
上面代码中,对象proto的foo属性不可写,结果proto的派生对象o,也不可以再自定义这个属性了。在严格模式下,这样做还会抛出一个错误。但是,有一个规避方法,就是通过覆盖属性描述对象,绕过这个限制,原因是这种情况下,原型链会被完全忽视。
Object.defineProperty(o, 'foo', {
value: 'b'
});
o.foo // 'b'
Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。
var o = Object.defineProperties({}, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});
Object.getOwnPropertyNames(o)
// ["p1", "p2"]
一般来说,系统原生的属性(即非用户自定义的属性)都是不可枚举的。
// 比如,数组实例自带length属性是不可枚举的
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]
// Object.prototype对象的自带属性也都是不可枚举的
Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ['hasOwnProperty',
// 'valueOf',
// 'constructor',
// 'toLocaleString',
// 'isPrototypeOf',
// 'propertyIsEnumerable',
// 'toString']
上面代码可以看到,数组的实例对象([])没有可枚举属性,不可枚举属性有length;Object.prototype对象也没有可枚举属性,但是有不少不可枚举属性。
Object.prototype.propertyIsEnumerable()
对象实例的propertyIsEnumerable方法用来判断一个属性是否可枚举。
var o = {};
o.p = 123;
o.propertyIsEnumerable('p') // true
o.propertyIsEnumerable('toString') // false
上面代码中,用户自定义的p属性是可枚举的,而继承自原型对象的toString属性是不可枚举的。
网友评论