彻底搞懂对象的数据属性描述符、存储属性描述符
属性描述符
js
let obj = {
name: "ziu",
age: 18
}
Object.defineProperty(obj, "height", {
value: 1.88
})
console.log(obj) // { name: 'ziu', age: 18 }
obj
对象的控制台输出中,并没有defineProperty
新定义的height
,这是因为不可枚举的(不可遍历的),在打印时并没有和其他属性一起输出。这个属性已经被添加到对象中,只不过不可见。
js
console.log(obj.height) // 1.88
属性描述符是一个对象,根据功能不同,可以分为两类:数据属性描述符和存储属性描述符
数据属性描述符
- 数据属性描述符(Data Properties)
value
该属性对应的值,默认undefined
configurable
该属性描述符是否可被改变、是否可被删除,默认为false
enumerable
该属性是否可被枚举,默认为false
writable
该属性是否可以被写入新的值,默认为false
没有用属性描述符定义的对象属性(直接使用.
语法),也是具有以上属性描述符的特性的,value
值为属性被赋值的值,其他configurable
、emumerable
、writable
默认值都为true
。注意,属性描述符区全为小写。
js
let obj = {
name: "ziu",
age: 18
}
// 数据属性描述符
Object.defineProperty(obj, "address", {
value: "Beijing", // 该属性对应的值,默认为undefine
configurable: false, // 该属性描述符是否可被改变、是否可被删除,默认为false
enumerable: true, // 该属性是否可被枚举,默认为false
writable: true // 该属性是否可以被写入新的值,默认为false
})
// configurable
delete obj.address
obj.address = "Shanghai"
console.log(obj.address) // Beijing
// enumerable
console.log(obj)
for(let key in obj) {
console.log(key)
}
console.log(Object.keys(obj))
// writable
obj.address = "Tianjin"
console.log(obj.address)
存储属性描述符
- 存储属性描述符(Accessor Properties)
get
当访问该属性时,会调用此函数,默认为undefined
。set
当属性值被修改时,会调用此函数,默认为undefined
。
注意,get
、set
描述符与vaule
、writable
描述符不共存。
configurable | enumerable | value | writable | get | set | |
---|---|---|---|---|---|---|
数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
js
let obj = {
name: "ziu",
age: 18,
_address: "Beijing"
}
// Accessor Properties
Object.defineProperty(obj, "address", {
enumerable: true,
configurable: true,
// value: "Beijing",
// writable: true,
get: function() {
return this._address
},
set: function(val) {
this._address = val
}
})
console.log(obj.address) // 调用getter() Beijing
obj.address = "Shanghai" // 调用setter()
console.log(obj._address) // Shanghai
应用场景
- 隐藏某个私有属性,希望直接被外界使用和赋值。(下划线开头的变量一般为私有属性)
- 获取某个属性被访问或赋值的时刻,可以设置伴随被访问或被赋值时,执行其他函数。
js
Object.defineProperty(obj, "address", {
get: function() {
bar()
return this._address
},
set: function(val) {
foo()
this._address = val
}
})
console.log(obj.address) // got address value once
obj.address = "Shanghai" // resetted address value once
function bar() {
console.log("got address value once")
}
function foo() {
console.log("resetted address value once")
}