Object.defineProperty 在当前很多框架的实现中都使用了它的特性来实现,我们准备写一系列文章来深入浅出的了解下,第一篇文章先大概熟悉并了解整个方法参数以及使用方式。
方法定义
简单来说Object.defineProperty 实现的就是在一个对象上定义一个新属性,或者是修改一个已经存在的属性
Object.defineProperty(obj, prop, descriptor)
参数
obj
要定义属性的对象
prop
要定义或修改的属性的名称或 Symbol
descriptor
要定义或修改的属性描述符
类型属性
这里根据 MDN 上,将defineProperty可以定义的两类属性分别分析下,一个是数据描述符、一个是存取描述符,并且这两种形式是不可以混用的。他们有共有属性和特有属性,我们下面都单独理一下。
描述符中属性默认参数
| 属性名称 | 默认值 |
|---|---|
| configurable | false |
| enumerable | false |
| value | undefined |
| writable | false |
| get | undefined |
| set | undefined |
数据描述符
数据描述符特有的两个属性 value 和 writable
value
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
writable: true // 是否可以改变
})
writable 是否可以改变属性的值
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc'
})
Obj.name = 'chenhh'
// writable 默认值是false,则属性值无法改变
console.log(Obj.name) // 'chencc'
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
writable: true
})
Obj.name = 'chenhh'
console.log(Obj.name) // 'chenhh'
存取描述符
getter: 是一种获得属性值的方法 默认为 undefined
setter: 是一种设置属性值的方法 默认为 undefined
let Obj = {}
let temp = null
Object.defineProperty(Obj, 'name', {
get: function () {
return temp
},
set: function (value) {
temp = value
}
})
Obj.name = 'chencc'
console.log(Obj.name) // 'chencc'
备注:在 get 和 set 设置对象的时候,需要设置一个 temp 的临时变量,都是通过临时变量赋值和改变值的方式,来改变
共有属性
configurable 是否可以删除
configurable 设置属性是否可以删除以及属性是否可以重新定义
eg1:
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
configurable: false,
writable: true
})
Obj.name = 'chenhh' // chenhh
delete Obj.name // false 无法删除属性
eg2:
let Obj = {}
Object.defineProperty(Obj,'name', {
value: 'chencc',
configurable: false
})
Object.defineProperty(Obj, 'name', {
value: 'chenhh'
})
// Cannot redefine property: name
这里实际上是 configurable 和 writable 同时为 false 了
eg3:
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
configurable: true,
writable: false
})
Obj.name = 'chenhh'
console.log(Obj.name) // 'chencc'
Object.defineProperty(Obj, 'name', {
value: 'chenhh'
})
console.log(Obj.name) // 'chenhh'
如果 configurable 为真,writable 为假,直接给属性无法赋值,但是可以通过重新定义的方式进行赋值,并且可以删除属性
eg4:
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
configurable: false,
writable: true
})
Object.defineProperty(Obj, 'name', {
value: 'chenhh'
})
总结
- configurable 为 false时,不能删除属性,且不能重新设置属性的描述(除了writable例外,可以把writable由 true 改为 false,但是无法将 writable 由 false 改为true),同时在 writable 为 true 的时候,可以修改 value 的值
enumerable 是否可以枚举
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc',
enumerable: false
})
Obj.subject = 'CS'
Object.defineProperty(Obj, 'age', {
value: 25,
enumerable: true
})
console.log(Object.keys(Obj)) // ['subject', 'age']
for (let key in Obj) {
console.log(key)
}
// subject
// age
Obj.propertyIsEnumerable('subject') // true
Obj.propertyIsEnumerable('age') // true
Obj.propertyIsEnumerable('name') // false
备注:写法的区别
eg1:
let Obj = {}
Obj.name = 'chencc'
// 等同于
Obj.defineProperty(Obj, 'name', {
value: 'chencc',
configurable: true,
writable: true,
enumerable: true
})
eg2
let Obj = {}
Object.defineProperty(Obj, 'name', {
value: 'chencc'
})
// 等同于
Obj.defineProperty(Obj, 'name', {
value: 'chencc',
configurable: false,
writable: false,
enumerable: false
})
总的来说,对于defineProperty对象的基础部分主要在两种描述和几个属性定义,大家把这个理解清楚就可以对于这些来做一些实际应用了。