JS中的属性描述对象 3

2018-05-07  本文已影响0人  诗和远方何你

可写性(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属性是不可枚举的。

上一篇 下一篇

猜你喜欢

热点阅读