JavaScript高级 对象增强
一、Object.defineProperty
属性都是直接定义在对象内部,或者直接添加到对象内部的
但是这样就不能对这个属性进行一些限制;比如属性是否可以通过delete删除,是否能在for in
遍历的时候被遍历出来
如果想要对一个属性进行比较精准的操作控制,就可以使用属性描述符
- 通过属性描述符可以精准的添加或者修改对象的属性
- 属性描述符需要使用
Object.defineProperty
来对属性进行添加或者修改
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
|
|
可接受三个参数:
- obj是要定义属性的对象
- prop是要定义或修改的属性名称或Symbol
- descriptor是要定义或修改的属性描述符
返回值
- 被传递给函数的对象
属性描述符的类型有两种:
- 数据属性描述符
- 存取属性描述符
二、数据属性描述符
数据属性描述符有四个特性:
-
[[Configuable]]: 表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符
- 当直接在对象上定义某个属性时,这个属性的 [[Configuable]] 为
true
- 当通过属性描述符定义一个属性时,这个属性的 [[Configuable]] 为
false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var obj = { name: 'mocha', age: 18 } Object.defineProperty(obj, 'name', { configurable: false // 告诉js引擎,obj对象的name属性不可以被删除 }) delete obj.name console.log(obj) // { name: 'mocha', age: 18 } // 通过 Object.defineProperty 添加一个新的属性 Object.defineProperty(obj, 'address', {}) delete obj.address console.log(obj) // { name: 'mocha', age: 18 }
- 当直接在对象上定义某个属性时,这个属性的 [[Configuable]] 为
-
[[Enumerable]]: 表示属性是否可以通过
for-in
或者Object.keys()
返回该属性- 当直接在对象上定义某个属性时,这个属性的 [[Enumerable]] 为
true
- 当通过属性描述符定义一个属性时,这个属性的 [[Enumerable]] 为
false
1 2 3 4 5 6 7 8 9 10 11
var obj = { name: 'mocha', age: 18 } Object.defineProperty(obj, 'name', { enumerable: false }) const keys = Object.keys(obj) console.log(keys) // age
- 当直接在对象上定义某个属性时,这个属性的 [[Enumerable]] 为
-
[[Writable]]: 表示是否可以修改属性的值
- 当直接在对象上定义某个属性时,这个属性的**[[Writable]]** 为
true
- 当直接通过属性描述符定义属性时,这个属性的**[[Writable]]** 为
false
1 2 3 4 5 6 7 8 9 10 11
var obj = { name: 'mocha', age: 18 } Object.defineProperty(obj, 'name', { writable: false }) obj.name = 'latte' console.log(obj.name) // mocha
- 当直接在对象上定义某个属性时,这个属性的**[[Writable]]** 为
-
[[value]]: 属性的value值,读取属性时会返回该值,修改属性时,会对其进行修改
- 默认情况下这个值是undefined
1 2 3 4 5 6 7 8 9 10 11
var obj = {} Object.defineProperty(obj, 'name', { configurable: false, enumerable: false, writable: false, value: 'mocha' }) console.log(obj.name) // mocha
三、存取属性描述符
存取属性描述符有四个特性:
- [[Configuable]]: 表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性
- 和数据属性描述符一致
- 当直接在对象上定义某个属性时,这个属性的 [[Configuable]] 为
true
- 当通过属性描述符定义一个属性时,这个属性的 [[Configuable]] 为
false
- [[Enumerable]]: 表示属性是否可以通过
for-in
或者Object.keys()
返回该属性- 和数据属性描述符一致
- 当直接在对象上定义某个属性时,这个属性的 [[Enumerable]] 为
true
- 当通过属性描述符定义一个属性时,这个属性的 [[Enumerable]] 为
false
- [[get]]: 获取属性时会执行的函数,默认为
undefined
- [[set]]: 设置属性时会执行的函数,默认为
undefined
|
|
四、Object.defineProperties
Object.defineProperties() 方法直接在对象上定义多个新的属性或者修改现有属性,并且返回该对象
|
|
五、对象的其他方法补充
-
获取对象的属性描述符
-
禁止对象扩展新属性:preventExtensions
-
给对象添加新的属性会失败(在严格模式下会报错)
1 2 3 4 5 6 7 8 9 10
var obj = { name: 'mocha', age: 18, } Object.preventExtensions(obj) obj.address = '广州市' console.log(obj) // { name: 'mocha', age: 18 }
-
-
密封对象,不允许配置和删除属性:seal
-
实际是调用preventExtensions
-
并且将现有属性的configurable设置为
false
1 2 3 4 5 6 7 8 9 10
var obj = { name: 'mocha', age: 18, } Object.seal(obj) delete obj.name console.log(obj) // { name: 'mocha', age: 18 }
-
-
冻结对象,不允许修改现有属性:freeze
-
实际上是调用seal
-
并且将现有属性的writable设置为
false
1 2 3 4 5 6 7 8 9 10
var obj = { name: 'mocha', age: 18, } Object.freeze(obj) obj.name = 'latte' console.log(obj) // { name: 'mocha', age: 18 }
-
- 原文作者:Gmi_61
- 原文链接:https://www.huangzhishou.com/post/JavaScript%E9%AB%98%E7%BA%A7-%E5%AF%B9%E8%B1%A1%E5%A2%9E%E5%BC%BA.html
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。