sunnyxujian's blog sunnyxujian's blog
首页
  • JavaScript
  • CSS
  • HTML和浏览器
  • Vue
  • Vue3
  • React
  • 基础知识
  • webpack
  • rollup
  • vite
  • 其他
  • Nodejs
  • 网络
  • TypeScript
  • 架构设计
  • 性能优化
  • 数据结构和算法
  • JavaScript教程 笔记
  • ES6 教程 笔记
  • TypeScript 从零实现 axios
  • Git学习 笔记
  • 渲染器原理
  • TypeScript 笔记
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网站
  • 资源
  • Vue资源
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 友链
  • 关于
GitHub (opens new window)

xujian

劝君惜取少年时。
首页
  • JavaScript
  • CSS
  • HTML和浏览器
  • Vue
  • Vue3
  • React
  • 基础知识
  • webpack
  • rollup
  • vite
  • 其他
  • Nodejs
  • 网络
  • TypeScript
  • 架构设计
  • 性能优化
  • 数据结构和算法
  • JavaScript教程 笔记
  • ES6 教程 笔记
  • TypeScript 从零实现 axios
  • Git学习 笔记
  • 渲染器原理
  • TypeScript 笔记
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网站
  • 资源
  • Vue资源
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 友链
  • 关于
GitHub (opens new window)
  • Vue

  • Vue3

    • 初识Proxy,Reflect,WeakMap
      • 1.Proxy
      • 2.Reflect
      • 3. WeakMap
        • 3.1WeakMap的特点
        • 3.2WeakMap和Map的区别
    • 手写vue3-compiler-dom之AST篇
  • React

  • 框架
  • Vue3
xujian
2021-10-17

初识Proxy,Reflect,WeakMap

Vue3源码reactive的核心实现用到了Proxy、Reflect、WeakMap等新语法,所以理解其响应式原理的前提是先熟悉这些新语法。

# 1.Proxy

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

var obj = new Proxy({}, {
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
});

obj.count = 1
//  setting count!
++obj.count
//  getting count!
//  setting count!
//  2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

上面代码对一个空对象架设了一层拦截,重定义了属性的读取(get)和设置(set)行为。receiver 是指的Proxy的实例。Reflect 是反射对象。

var proxy = new Proxy(target, handler);
1

Proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。其中,new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。 target 可以接收对象,函数 handler 接收的是对象如果不传或者传空对象,那么Proxy的实例相当于未被代理

提示

new Proxy(target, {...})是浅代理,也就是说只会代理target这个对象的第一层,如果要代理对象的每一层,做递归处理即可。

# 2.Reflect

Reflect 意为反射,是ES6为了操作对象设计的API,一般配合Proxy一起使用,它与Proxy内部的api完全一致。设计这个API的目的有以下几个

  1. 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
  2. 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
  3. 让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
  4. Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。

Reflect对象一共有 13 个静态方法。

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

上面这些方法的作用,大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。

# 3. WeakMap

# 3.1WeakMap的特点

  1. WeakMap 只接受对象作为键名
  2. WeakMap 的键名所引用的对象是弱引用 这个弱引用的特性,就是 WeakMaps 保持了对键名所引用的对象的弱引用,即垃圾回收机制不将该引用考虑在内。只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

也正是因为这样的特性,WeakMap 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakMap 不可遍历。

# 3.2WeakMap和Map的区别

下面的这个例子很好的演示了他们之间的区别

const map = new Map();
const weakmap = new WeakMap();
(function(){
  const foo = {a: 1};
  const bar = {b: 2};
  map.set(foo,1)
  weakmap.set(bar,2)
})()

console.log(map)
console.log(weakmap)
1
2
3
4
5
6
7
8
9
10
11

立即执行函数(IIFE)执行完毕之后,由于bar是弱引用,它将会被垃圾回收器回收,而foo不会回收,它会一直保留在map中,如下图所示:

map和weakmap

编辑 (opens new window)
#ES6#Vue3
上次更新: 2022/05/23, 15:08:15
Vue在模板中渲染JSX
手写vue3-compiler-dom之AST篇

← Vue在模板中渲染JSX 手写vue3-compiler-dom之AST篇→

最近更新
01
😍Vue3和React都在用的函数式编程,学起来~
02-03
02
链表
11-24
03
基础类型
11-18
更多文章>
Theme by Vdoing | Copyright © 2020-2023 xujian | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式