Skip to content

Commit

Permalink
feat(): new docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Cap committed Dec 27, 2024
1 parent 1d8c0b3 commit bdaacc4
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 1 deletion.
113 changes: 113 additions & 0 deletions src/Vue/Object.defineProperty与Proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
title: 'Object.defineProperty与Proxy' # 当前页面内容标题,默认为 Markdown 文件中的第一个 h1 标签内容
shortTitle: '' # 当前页面的短标题
description: '' # 当前页面内容描述
icon: '' # 当前页面图标的 FontClass 或文件路径 (建议填写)。
author: {
name: 'Cap'
}
isOriginal: true # 当前文章是否为原创。
date: 2024-12-27 # 写作时间。
category: '' # 分类
tag: 'vue' # 标签
sticky: 241227 # 是否在列表中置顶。当填入数字时,数字越大,排名越靠前
star: true # 是否收藏在博客主题的文章列表中。当填入数字时,数字越大,排名越靠前。
article: true # 是否将该文章添加至文章列表中
timeline: true # 是否将该文章添加至时间线中
---

## Object.defineProperty

Object.defineProperty 是 ES5 引入的方法,用于在对象上定义新属性或修改现有属性。

```javascript
let obj = {};
Object.defineProperty(obj, 'prop', {
value: 42,
writable: false
});
```

### 优点

- 兼容性好,支持旧版浏览器
- 可以精确定义属性的特性(如可写、可枚举、可配置)

### 缺点

- 不能监听数组的变化(如通过索引修改数组元素)
- 不能监听新增属性
- 需要递归遍历对象的所有属性来实现深度监听

## Proxy

Proxy 是 ES6 引入的特性,它可以创建一个对象的代理,从而实现基本操作的拦截和自定义。

```javascript
let obj = {};
let proxy = new Proxy(obj, {
get(target, property) {
console.log(`Getting ${property}`);
return target[property];
},
set(target, property, value) {
console.log(`Setting ${property} to ${value}`);
target[property] = value;
return true;
}
});
```

### 优点

- 可以监听数组变化
- 可以监听新增属性
- 不需要递归遍历,可以懒处理
- 提供了更多的拦截方法(如 deleteProperty, has 等)

### 缺点

- 兼容性较差,不支持 IE


## 大规模数据处理的差异


在处理大规模数据时,这两种方法有以下主要差异:

### A. 初始化性能:

- Object.defineProperty 需要递归遍历对象的所有属性,对于大对象来说,初始化时间可能会很长。
- Proxy 不需要初始化时遍历,可以懒处理,因此初始化速度更快。


### B. 内存占用:

- Object.defineProperty 会为每个属性创建 getter 和 setter,可能导致较高的内存占用。
- Proxy 创建的是整个对象的代理,不会为每个属性创建额外的函数,内存占用相对较低。


### C. 动态属性处理:

- Object.defineProperty 不能监听新增属性,需要额外的处理(如 Vue 2.x 中的 Vue.set)。
- Proxy 可以自动监听新增属性,无需额外处理。


### d. 数组处理:

- Object.defineProperty 不能有效地监听数组的变化,需要额外的处理。
- Proxy 可以直接监听数组的变化,包括通过索引修改元素。

## 性能比较

理论上,在处理大规模数据时,Proxy 的性能应该更好:

1. 初始化更快:Proxy 不需要递归遍历对象,初始化大对象时更快。
2. 懒处理:Proxy 可以在真正访问属性时才执行拦截操作,而 Object.defineProperty 需要预先定义所有属性的 getter 和 setter。
3. 更少的内存开销:Proxy 为整个对象创建一个代理,而不是为每个属性创建 getter 和 setter。
4. 更好的数组处理:Proxy 可以直接监听数组操作,而 Object.defineProperty 需要额外的处理。

然而,实际性能可能因具体使用场景和浏览器实现而异。在某些情况下,Object.defineProperty 可能表现更好,特别是在旧版浏览器中。

## 结论:
对于现代web应用,特别是处理大规模数据时,Proxy 通常是更好的选择。它提供了更强大和灵活的功能,理论上有更好的性能。然而,如果需要支持旧版浏览器(如 IE),则可能需要使用 Object.defineProperty。
141 changes: 141 additions & 0 deletions src/Vue/Object.defineProperty可能表现更好的场景.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
title: 'Object.defineProperty可能表现更好的场景' # 当前页面内容标题,默认为 Markdown 文件中的第一个 h1 标签内容
shortTitle: '' # 当前页面的短标题
description: '' # 当前页面内容描述
icon: '' # 当前页面图标的 FontClass 或文件路径 (建议填写)。
author: {
name: 'Cap'
}
isOriginal: true # 当前文章是否为原创。
date: 2024-12-27 # 写作时间。
category: '' # 分类
tag: 'vue' # 标签
sticky: 241227 # 是否在列表中置顶。当填入数字时,数字越大,排名越靠前
star: true # 是否收藏在博客主题的文章列表中。当填入数字时,数字越大,排名越靠前。
article: true # 是否将该文章添加至文章列表中
timeline: true # 是否将该文章添加至时间线中
---

## 简单对象的监听

当我们只需要监听一个简单对象的少量属性时,Object.defineProperty 可能会有更好的性能。这是因为它不需要创建额外的代理对象。

```javascript
let obj = {};
Object.defineProperty(obj, 'name', {
get() {
console.log('Getting name');
return this._name;
},
set(value) {
console.log('Setting name');
this._name = value;
}
});
```

在这种情况下,Object.defineProperty 直接修改了原对象,而 Proxy 会创建一个新的代理对象。

## 频繁访问的小型对象

对于频繁访问的小型对象,Object.defineProperty 可能会有更好的性能,因为它不需要通过代理来访问属性。

```javascript
let person = { name: 'John', age: 30 };
Object.keys(person).forEach(key => {
let value = person[key];
Object.defineProperty(person, key, {
get() {
console.log(`Getting ${key}`);
return value;
},
set(newValue) {
console.log(`Setting ${key}`);
value = newValue;
}
});
});
```

在这个例子中,直接访问 person.name 或 person.age 可能比通过 Proxy 访问更快。

## 旧版浏览器兼容性

在需要支持旧版浏览器(如 IE11)的情况下,Object.defineProperty 是唯一的选择,因为这些浏览器不支持 Proxy。

```javascript
// 这在 IE11 中可以工作
let obj = {};
Object.defineProperty(obj, 'prop', {
value: 42,
writable: true
});

// 这在 IE11 中会报错
let proxy = new Proxy({}, {
get(target, prop) {
return 42;
}
});
```

## 特定属性的精细控制

当我们需要对特定属性进行精细控制时,Object.defineProperty 可能更合适。例如,我们可以轻松地创建一个只读属性:

```javascript
let obj = {};
Object.defineProperty(obj, 'constant', {
value: 42,
writable: false,
configurable: false
});
```

虽然 Proxy 也可以实现类似的功能,但可能需要更多的代码。

## 与旧代码的兼容性

在一些遗留系统中,可能已经大量使用了 Object.defineProperty。在这种情况下,继续使用 Object.defineProperty 可能会更容易维护和理解。

```javascript
// 假设这是一个已存在的代码库
function createPerson(name, age) {
let person = {};
Object.defineProperty(person, 'name', {
get() { return name; },
set(value) { name = value; }
});
Object.defineProperty(person, 'age', {
get() { return age; },
set(value) { age = value; }
});
return person;
}

// 继续使用 Object.defineProperty 可能比引入 Proxy 更容易维护
```

## 单一属性的监听

当我们只需要监听一个对象的单一属性时,Object.defineProperty 可能会有更好的性能,因为它不需要为整个对象创建代理。

```javascript
let obj = { a: 1, b: 2, c: 3 };
Object.defineProperty(obj, 'a', {
get() {
console.log('Getting a');
return this._a;
},
set(value) {
console.log('Setting a');
this._a = value;
}
});
```

在这个例子中,我们只监听了 'a' 属性,而 'b' 和 'c' 保持不变。使用 Proxy 可能会对所有属性都进行不必要的代理。

## 总结

虽然 Proxy 在大多数现代场景下可能更优,但 Object.defineProperty 在某些特定情况下仍然有其优势。这些情况主要包括:简单对象的监听、频繁访问的小型对象、需要旧版浏览器兼容性、特定属性的精细控制、与旧代码的兼容性,以及单一属性的监听等。
1 change: 0 additions & 1 deletion src/Vue/Vue与React的区别.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ sticky: 100 # 是否在列表中置顶。当填入数字时,数字越大,排
star: true # 是否收藏在博客主题的文章列表中。当填入数字时,数字越大,排名越靠前。
article: true # 是否将该文章添加至文章列表中
timeline: true # 是否将该文章添加至时间线中

---

- [参考链接](https://mp.weixin.qq.com/s/6QTdeM2l1htofCnKLZS6yw)
Expand Down

0 comments on commit bdaacc4

Please sign in to comment.