ES6语法Proxy的基本使用

最近接触Vue3越来越多,大家都知道Vue3中的ref是使用get和set拦截value实现的,所以用ref定义的数据需要用.value的方式来访问,但是reactive是使用proxy和reflect来实现的,就趁着这个时间把Proxy和Reflect 先看一看,本篇仅限于Proxy,Reflect会单独开一篇笔记。

基本概念

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义

Proxy是一个可构造对象,通过new创建实例。

语法:

1
const p = new Proxy(target, handler)

参数:

  • target

    要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

  • handler

    一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

Proxy的方法

除了直接 new Proxy 对象外,Proxy 构造函数上还有一个静态函数 revocable可以构造一个能被销毁的代理对象。

与new Proxy创建的代理对象不同,revocable还会返回一个销毁函数:

1
2
3
4
5
6
Proxy.revocable( target: Object, handlers: Object ) : Object

Proxy.revocable( target, handlers ) → {
proxy: Proxy, // 代理对象
revoke: ƒ () // 销毁函数
}

销毁函数不需要任何参数,我们可以随时调用销毁函数将代理对象和目标对象的代理关系断开。断开代理后,再对代理对象执行任何操作都会抛出 TypeError 错误。

Proxy特点

  • Proxy 在处理属性名的时候会把除 Symbol 类型外的所有属性名都转化成字符串,所以处理函数在判断属性名时需要尤其注意。
  • 对代理对象的任何操作都会被拦截,一旦代理对象被创建就没有办法再修改它本身。
  • Proxy 的代理是非常底层的,在没有主动暴露原始目标对象的情况下,没有任何办法越过代理对象访问目标对象
  • Proxy 代理的目标只能是对象,不能是 JavaScript 中的原始类型

handler方法

handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap)。

所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。

  • apply()
  • construct()
  • defineProperty ()
  • deleteProperty ()
  • get ()
  • getOwnPropertyDescrip ()
  • getPrototypeOf ()
  • has ()
  • isExtensible ()
  • ownKeys ()
  • preventExtensions ()
  • set ()
  • setPrototypeOf ()

handler的方法我们称之为陷阱。每个陷阱用于捕获一种行为。

defineProperty和deleteProperty

defineProperty用于拦截Object.defineProperty操作,返回一个布尔值,表示该操作是否成功。

deleteProperty用于拦截属性的delete操作,也是返回布尔值。

get

get用于拦截属性的读取操作,是很常用的属性。

1
2
3
4
var p = new Proxy(target, {
get: function(target, property, receiver) {
}
});
  • target : 目标对象。

  • property : 被获取的属性名。

  • receiver : Proxy 或者继承 Proxy 的对象

set

set方法拦截对属性值的操作

1
2
3
4
const p = new Proxy(target, {
set: function(target, property, value, receiver) {
}
});

应当返回一个布尔值。返回 true 代表属性设置成功

以上是一个基本介绍,具体细节望请查看mdn文档,proxy一般会用来配合reflect使用,下一节会介绍reflect。

作者

胡兆磊

发布于

2022-07-22

更新于

2022-10-23

许可协议