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 报错如下
存取描述符汇总如下
三、和属性描述符相关的几个函数
- Object.defineProperty
- Object.defineProperties
- 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) |
输出如图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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