ZiuChen.github.io/docs/article/彻底搞懂对象的数据属性描述符、存储属性描述符.md
2023-02-05 15:07:58 +08:00

124 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 彻底搞懂对象的数据属性描述符、存储属性描述符
## 属性描述符
```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
```
### 应用场景
1. 隐藏某个私有属性,希望直接被外界使用和赋值。(下划线开头的变量一般为私有属性)
2. 获取某个属性被访问或赋值的时刻,可以设置伴随被访问或被赋值时,执行其他函数。
```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")
}
```