vue-java-tutorials/vue2-tutorials/import-script/3-Object.defineProperty.md

77 lines
2.3 KiB
Markdown
Raw Permalink Normal View History

2025-06-14 18:16:48 +08:00
# `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');
```