1

对象属性描述符

  1. 可写(writable attribute),表明是否可以设置该属性的值
  2. 可枚举(enumerable attribute),表明是否可以通过for/in循环返回该值
  3. 可配置(configurable attribute),表明是否可以删除或修改该属性
    在es5之前,通过代码给对象创建的所有属性都是可写的、可枚举的和可配置的。在es5中则可以对这些特性加以配置

writable

示例代码:

var one = {}
Object.defineProperty(one, "a", {
  value : 1,
  writable : false,
  configurable: true,
  enumerable: true
})
one.a = 2;
console.log(one.a) //1

如示例,当将对象的属性的writable特性定义为false时,对属性值的修改就会静默失败

configurable

只要属性是可配置的,就可以使用defineProperty()方法来修改属性:

var one = {}
Object.defineProperty(one, "a", {
  value : 1,
  writable : true,
  configurable: false,
  enumerable: true
})
console.log(one.a) //1
one.a = 2;
console.log(one.a) //2
delete one.a
console.log(one.a) //2
Object.defineProperty(one, "a", {
  value: 3,
  writable: true,
  configurable: true,
  enumerable: true
}) //TypeError

当属性的configurable特性设置为false时,此属性无法使用delete删除,操作会默认失败,因为此属性是不可配置的,同时无法再修改configurable特性,会产生一个TypeError,即configurable修改成false是单向操作

enumerable

此描述符控制的是属性是否会出现在对象的属性枚举中,比如说for..in循环。如果把enumerable设置成false,这个属性就不会出现在枚举中,虽然可以正常访问。

var one = {b:2}
Object.defineProperty(one, "a", {
  value : 1,
  writable : true,
  configurable: true,
  enumerable: false
})
for (var key in one) {
  console.log(key + '---' + one[key]) //b---2
}

如上例所示,one对象定义了一个不可枚举的属性a,那么在for..in循环遍历时就无法获取到a属性,当你不希望某些特殊属性出现在枚举中,那就把它设置成enumerable:false

Getter和Setter

在es5中可以使用getter和setter部分改写默认操作,但是只能应用在当个属性上,无法应用在整个对象上。getter是一个隐藏函数,会在获取属性值时调用。setter也是一个隐藏函数,会在设置属性值时调用

var one = {
  get a() {
    return this._a_;
  },
  set a(val) {
    this._a_ = val * 2
  }
}
one.a = 2
console.log(one.a) //4

Tips:当只对属性定义getter而没有定义setter时,此属性进行复制操作时将被忽略,赋值会失败但是不会报错

检测属性

js对象可以看作是属性的集合,因此我们会经常检测集合中成员的所属关系,即判断某个属性是否存在于某个对象中。可以通过in运算符、hasOwnProperty()和propertyIsEnumerable()方法来检测

in和hasOwnProperty

in运算符左侧是属性名,右侧是对象,如果对象的自由属性或继承属性中包含这个属性则返回true,对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性。对于继承属性将返回false:

var one = {
  a:1
}
console.log('a' in one) //true
console.log('b' in one) //false
console.log('toString' in one) //true
console.log(one.hasOwnProperty('a')) //true
console.log(one.hasOwnProperty('b')) //false
console.log(one.hasOwnProperty('toString')) //false

propertyIsEnumerable

propertyIsEnumerable()会检查给定的属性是否直接存在于对象中并且满足enumerable:true:

var one = {}
Object.defineProperty(one, "a", {
  value : 1,
  enumerable: true
})
Object.defineProperty(one, "b", {
  value : 2,
  enumerable: false
})
console.log(one.propertyIsEnumerable('a')) //true
console.log(one.propertyIsEnumerable('b')) //false
console.log(Object.keys(one)) //['a']
console.log(Object.getOwnPropertyNames(one)) //['a','b']

william
2.7k 声望826 粉丝

love and share


« 上一篇
this绑定规则