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

一、数据属性描述符

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

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

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

1
2
3
4
5
6
7
8
9
10
11
12
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 的属性

1
2
3
4
5
6
7
8
9
10
11
12
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 值

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

 

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

1
2
3
4
5
6
7
8
9
10
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
}

也即

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

等同于

1
2
3
4
5
6
7
8
9
10
11
12
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,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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) // 无输出,不能遍历
}

也即

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

等同于

1
2
3
4
5
6
Object.defineProperty(obj, 'name', {
    value: 'John',
    configurable: false,
    writable: false,
    enumerable: false      
})

 

数据属性描述符汇总如下

 

二、存取属性描述符

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

1
2
3
4
5
6
name: {
    get: function() { ... },
    set: function(newVal) { ... },
    enumerable: true,
    configurable: true
}

 

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 报错如下

 

存取描述符汇总如下

 

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

  1. Object.defineProperty
  2. Object.defineProperties
  3. Object.getOwnPropertyDescriptor

 

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

1
2
3
4
5
6
7
8
9
10
Object.defineProperties(obj, {
    name: {
        value: 'John',
        writable: true
    },
    age: {
        value: 30,
        enmuerable: true
    }
})

 

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

1
2
3
4
5
6
7
8
9
10
var obj = {}
 
Object.defineProperty(obj, 'name', {
    value: 'Backus',
    writable: true,
    enumerable: true
})
 
var des = Object.getOwnPropertyDescriptor(obj, 'name')
console.log(des)

输出如图

 

posted on   snandy  阅读(4143)  评论(1编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
历史上的今天:
2011-03-15 IE6/7 double padding-bottom Bug
2011-03-15 IE6 double margin-left Bug
2011-03-15 servlet下利用json-lib
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示