彻底搞懂对象的数据属性描述符、存储属性描述符
属性描述符
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该属性对应的值,默认undefinedconfigurable该属性描述符是否可被改变、是否可被删除,默认为falseenumerable该属性是否可被枚举,默认为falsewritable该属性是否可以被写入新的值,默认为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")
}