阅读 179

Proxy 对象简介 | 周末学习

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

本文已参与周末学习计划,点击查看详情

关于Vue3 中的数据响应式功能,我们大家应该都知道,它是通过 ES6的代理模式——Proxy 对象实现的,今天我们来简单认识下何为 Proxy 对象。

Proxy 的定义

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

proxy修改的是程序默认形为,就形同于在编程语言层面上做修改,属于元编程(meta programming),即对编程语言进行编程。

  • 元编程(英语:Metaprogramming,又译超编程,是指某类计算机程序的编写,这类计算机程序编写或者操纵其它程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作.

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

Proxy 的基本语法

ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。

var proxy = new Proxy(target, handler);
复制代码
  • target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 proxy 的行为。

Proxy 使用示例

下面是关于 Proxy 使用的一个基本示例:

const person = {
  name: "superMan",
};

const proxy = new Proxy(man, {
  get(target, property, receiver) {
    console.log(`正在获取 ${property} 属性`)
    return target[property];
  },
});

console.log(proxy.name);
console.log(proxy.age);
复制代码

在以上示例中, Proxy 构造函数接受 person 对象为代理目标,创建了一个代理对象。在创建代理对象时,我们定义了一个 get 捕获器,用于捕获代理目标属性读取的操作。 捕获器的作用就是用于拦截用户对目标对象属性读取的相关操作,在这些操作传播到目标对象之前,会先调用对应的捕获器函数,从而拦截并修改相应的行为。

在设置了 get 捕获器之后,当成功运行以上的示例代码,控制台会输出以下结果:

正在获取 name 属性
superman
正在读取 age 属性
undefined
复制代码

通过观察以上输出结果,我们可以发现 get 捕获器 不仅可以拦截已知属性的读取操作,也可以拦截未知属性的读取操作。

Proxy 实例当做原型对象

Proxy 实例也可以作为其他对象的原型对象:

var proxy = new Proxy({}, {
  get: function(target, property) {
    return 35;
  }
});
 
let obj = Object.create(proxy);
obj.time  // 35
复制代码

上面代码中,proxy对象是obj对象的原型,obj对象本身并没有time属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截。

Proxy 实例的方法

在创建 Proxy 对象时,除了定义 get 捕获器 之外,我们还可以定义其他的捕获器,比如 set、apply 、 has或者 deleteProperty 等。

get()

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

set()

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

apply()

apply方法拦截函数的调用、callapply操作。

apply方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组。

has()

has方法用来拦截HasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in运算符。

has方法可以接受两个参数,分别是目标对象、需查询的属性名。

deleteProperty()

deleteProperty方法用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。

defineProperty()

defineProperty方法拦截了Object.defineProperty操作。

总结

Proxy就是拦截层,你给出被拦截的对象,外界访问这个对象必须先通过拦截层,即访问Proxy的实例对象。通过Proxy为外界访问进行过滤和改写,如赋值时需满足某些条件。

学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!

大家好!我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!

知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

文章分类
前端
文章标签