mirror of
https://github.com/ZiuChen/ZiuChen.github.io.git
synced 2025-08-17 23:19:55 +08:00
124 lines
4.0 KiB
Markdown
124 lines
4.0 KiB
Markdown
# 彻底搞懂对象的数据属性描述符、存储属性描述符
|
||
|
||
## 属性描述符
|
||
|
||
```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")
|
||
}
|
||
```
|
||
|