77 lines
2.3 KiB
Markdown
77 lines
2.3 KiB
Markdown
# `Object.defineProperty` 方法
|
||
|
||
## 一、基本概念
|
||
|
||
`Object.defineProperty()` 是 JavaScript 中用于直接在一个对象上定义一个新属性,或者修改一个对象的现有属性的方法。它允许精确控制属性的行为特性。
|
||
|
||
## 属性描述符详解
|
||
|
||
### 1. 数据描述符(已注释部分)
|
||
```javascript
|
||
{
|
||
value: 18, // 属性值
|
||
enumerable: true, // 是否可枚举(for...in或Object.keys())
|
||
writable: true, // 是否可修改
|
||
configurable: true // 是否可删除或修改特性
|
||
}
|
||
```
|
||
|
||
### 2. 存取描述符(实际使用部分)
|
||
```javascript
|
||
{
|
||
get() {
|
||
// 读取属性时调用
|
||
return age;
|
||
},
|
||
set(value) {
|
||
// 设置属性时调用
|
||
age = value;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 特性说明
|
||
|
||
| 特性 | 类型 | 默认值 | 描述 |
|
||
| ------------ | ---- | --------- | ------------------------ |
|
||
| configurable | 布尔 | false | 是否可删除属性或修改特性 |
|
||
| enumerable | 布尔 | false | 是否出现在枚举属性中 |
|
||
| value | 任意 | undefined | 属性值 |
|
||
| writable | 布尔 | false | 是否可被赋值运算符改变 |
|
||
| get | 函数 | undefined | 读取属性时调用的函数 |
|
||
| set | 函数 | undefined | 设置属性时调用的函数 |
|
||
|
||
## 使用场景
|
||
|
||
1. **实现数据响应式**(如Vue2的核心实现)
|
||
2. **创建私有属性**(通过getter/setter控制访问)
|
||
3. **属性访问拦截**(在读取或设置时执行额外操作)
|
||
4. **定义不可枚举属性**(如内置对象的一些方法)
|
||
|
||
## 注意事项
|
||
|
||
1. 数据描述符(value, writable)和存取描述符(get, set)不能同时使用
|
||
2. 默认情况下,通过defineProperty添加的属性不可枚举、不可写、不可配置
|
||
3. 在严格模式下,setter必须设置一个参数,否则会抛出错误
|
||
4. getter不应有副作用(如修改其他属性值)
|
||
|
||
**实现简单响应式**
|
||
|
||
```javascript
|
||
function defineReactive(obj, key, val) {
|
||
Object.defineProperty(obj, key, {
|
||
get() {
|
||
console.log(`读取 ${key}: ${val}`);
|
||
return val;
|
||
},
|
||
set(newVal) {
|
||
console.log(`设置 ${key}: ${newVal}`);
|
||
val = newVal;
|
||
}
|
||
});
|
||
}
|
||
|
||
const data = {};
|
||
defineReactive(data, 'message', 'Hello');
|
||
```
|