您的位置:首页 > 其它

ES5 数据属性描述符和存取描述符

2016-03-15 07:32 387 查看

一、数据属性描述符

对象是一个属性集合,对象的基本特征是属性名(name)和属性值(value)。ES5 增加了属性描述符,可以更细腻的控制属性的不同操作。属性描述符有 configurable、writable 和 enumerable。

属性描述符通常和 Object.defineProperty/Object.defineProperties 一起使用来定义属性,它也会受到诸如 Object.freeze/Object.seal 等方法改变。

1. configurable 当且仅当 configurable 为 true 时,该属性才能够被改变,也能够被删除(delete),默认为 false

var obj = {}

Object.defineProperty(obj, 'name', {
value: 'John'
})
// 不能 delete
delete obj.name // false

Object.defineProperty(obj, 'name', {
configurable: true,
value: 'John'
})
// 可以delete
delete obj.name // true


2. writable 当且仅当 writable 为 true 时,该属性才能被赋值运算符(=)改变,默认为 false

var obj = {}

Object.defineProperty(obj, 'name', {
value: 'John'
})
obj.name = 'Backus' // 修改不起作用,仍然是 John,严格模式中会报错阻止修改

Object.defineProperty(obj, 'name', {
writable: true,
value: 'John'
})
obj.name = 'Backus' // 被改为了 backus


3. enumerable 当且仅当 enumerable 为 true 时,该属性才能够出现在对象的枚举属性(for in)中,默认为 false

var obj = {}

Object.defineProperty(obj, 'name', {
value: 'John'
})
// 不能遍历
for (var a in obj) {
console.log(a) // 无输出
}

Object.defineProperty(obj, 'name', {
enumerable: true,
value: 'John'
})
// 可以遍历
for (var a in obj) {
console.log(a) // 输出 "name"
}


ES6 的 Object.keys 只返回 enumerable=true 的属性

var obj = {name: 'John'}

Object.defineProperty(obj, 'name', {
value: 'Backus',
enumerable: true
})
Object.defineProperty(obj, 'age', {
value: 30,
enumerable: false
})

Object.keys(obj) // ['name']


可以通过 propertyIsEnumerable 方法判断属性的 enumerable 值

obj.propertyIsEnumerable('name') // true
obj.propertyIsEnumerable('age')  // false


4. 使用 ES3(传统的) JSON 方式定义对象,其 configurable/writable/enumerable 默认都是 true,如下

var obj = {name: 'John', age: 30}

// configurable
delete obj.name // true
// writable
obj.age = 32 // true
// enumerable
for (var a in obj) {
console.log(a) // age
}


也即

var obj = {name: 'John', age: 30}


等同于

Object.defineProperty(obj, 'name', {
value: 'John',
configurable: true,
writable: true,
enumerable: true
})
Object.defineProperty(obj, 'age', {
value: 33,
configurable: true,
writable: true,
enumerable: true
})


  

5. 使用 ES5 的 Object.defineProperty/Object.defineProperties 方式定义对象,其 configurable/writable/enumerable 默认都是 false,如下

var obj = {}

Object.defineProperty(obj, 'name', {
value: 'John'
})
Object.defineProperty(obj, 'age', {
value: 33
})

// configurable
delete obj.name // false
// writable
obj.age = 32 // false
// enumerable
for (var a in obj) {
console.log(a) // 无输出,不能遍历
}


也即

Object.defineProperty(obj, 'name', {
value: 'John'
})


等同于

Object.defineProperty(obj, 'name', {
value: 'John',
configurable: false,
writable: false,
enumerable: false
})


数据属性描述符汇总如下



二、存取属性描述符

存取描述符是由一对 getter-setter 函数功能来描述的属性,格式为

name: {
get: function() { ... },
set: function(newVal) { ... },
enumerable: true,
configurable: true
}


例如

var obj = {}

Object.defineProperty(obj, 'name', {
configurable: true,
enumerable: true,
get: function() {
console.log('get')
return this.value
},
set: function(newVal) {
console.log('set')
this.value = newVal
}
})

// 赋值会调用 set 方法
obj.name = 'John'
// 取值会调用 get 方法
obj.name


与上述的属性描述符只能存在一种,即二选一,不能同时存在,否则会报错

var obj = {}

// 错误方式一
Object.defineProperty(obj, 'name', {
value: 'John',
get: function() {
console.log('get')
return this.value
}
})

// 错误方式二
Object.defineProperty(obj, 'name', {
writable: true,
get: function() {
console.log('get')
return this.value
}
})


Firefox 报错如下



存取描述符汇总如下



三、和属性描述符相关的几个函数

Object.defineProperty

Object.defineProperties

Object.getOwnPropertyDescriptor

Object.defineProperty 上面已经介绍过,Object.defineProperties 批量定制对象属性,内部其实循环方式调用 Object.defineProperty

Object.defineProperties(obj, {
name: {
value: 'John',
writable: true
},
age: {
value: 30,
enmuerable: true
}
})


Object.getOwnPropertyDescriptor 返回该对象某属性的描述器,描述器自身是一个对象

var obj = {}

Object.defineProperty(obj, 'name', {
value: 'Backus',
writable: true,
enumerable: true
})

var des = Object.getOwnPropertyDescriptor(obj, 'name')
console.log(des)


输出如图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: