深入浅出JS—15 ES6中Proxy及Reflect的使用

在一些前端框架中,常常需要监听数据变化,页面进行响应。为了监听对象的变化,需要对对象的操作进行捕获。本文着重介绍ES6中Proxy代理对象的使用,以及涉及到的映射对象Reflect使用

1. Proxy的设计初衷

为了监听对象的属性操作,在ES6之前一般借助于Object.defineProperty来实现,但有以下缺点

  1. Object.defineProperty设计初衷并不是要监听属性
  2. 对于新增属性、删除属性监听不到
  3. 将原来对象修改了(数据属性描述符–》存取属性描述符),不应该改变原始对象

在ES6中,新增了一个Proxy类,Proxy翻译为“代理”,是用于帮助我们创建一个代理的:

  • 如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象)
  • 之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作

2. Proxy类用法

const objProxy = new Proxy(obj, handler);
其中参数obj是要代理的原始对象,handler是捕获器对象,包含13中捕获器方法

// 1 原始对象
const obj = { name: "xs", age: 18 };
console.log(obj);

// 2 代理对象
// new Proxy(target, handler)第一个参数为要代理的目标对象,第二个为对对象操作的监听处理对象
const objProxy = new Proxy(obj, {}); 
console.log(objProxy);

浏览器中打印如下:可以清楚看到第一个是对象类型Object,第二个是Proxy类型对象
在这里插入图片描述

3. Proxy捕获器

那么,代理对象如何监听我们的操作呢,就需要用到捕获器,Proxy中有13种捕获器
在这里插入图片描述

4种常用捕获器(熟练)

创建Proxy对象的第二个入参为handler对象,里面可以设置13中捕获器方法,但最常用的只有4种:get
set, has, deleteProperty

const obj = {
  name: "xs",
  age: 18,
};

const objProxy = new Proxy(obj, {
  // 获取值 捕获器 target:obj,
  get(target, key) {
    console.log(`监听到对象的${key}属性被访问了`, target);
    return target[key];
  },

  // 设置值 捕获器
  set(target, key, newValue) {
    console.log(`监听到对象的${key}属性被赋值了`, target);
    target[key] = newValue;
  },
  
  // has 捕获器
  has(target, key) {
    console.log(`监听到对象的${key}属性in操作`, target);
    target.has(key)
  },

 // delete 捕获器
  deleteProperty(target, key) {
    console.log(`监听到对象的${key}属性删除操作`, target);
    delete target[key];
  },
});

调用

console.log(objProxy.name); // get
objProxy.name = 'kobe'; // set
console.log('name' in obj) // has
delete obj.name // deleteProperty

2种与函数相关的捕获器(了解)

  • apply 捕获函数的apply方法
  • construct 捕获函数作为构造函数
// 1 创建函数对象
function foo() {
  console.log(this);
}

// 2 创建函数代理对象
const fooProxy = new Proxy(foo, {
  // 设置apply捕获器
  apply(target, thisArg, argArray) {
    console.log(`监听函数${target.name}的apply操作`);
    target.apply(thisArg, argArray);
  },
 
  // 设置构造函数捕获器 
  construct(target, argArray) {
    console.log(`监听函数${target.name}的construct操作`);
    return new target(...argArray);
  }
});

// 3 调用代理对象
fooProxy(); // 不会被捕获
fooProxy.apply({ name: "xs" }, ["dsh", "dshjk"]); // 监听函数foo的apply操作
const f = new fooProxy(); // 监听函数foo的construct操作

4. Reflect映射对象

Reflect也是ES6中提出的一个新对象,字面意思是反射。(看着高大上,其实很简单)
简单认知:Reflect是Object的一个替身。Object.getOwnProperty()和Reflect.getOwnProperty()一样

Reflect的作用

  • 如果我们有Object可以做这些操作,那么为什么还需要有Reflect这样的新增对象呢?
    • 因为在早期的ECMA规范中没有考虑到这种对 对象本身 的操作如何设计会更加规范,所以将这些API放到了Object上面,但是Object作为一个构造函数,这些操作实际上放到它身上并不合适
    • 另外还包含一些类似于 in、delete操作符,让JS看起来是会有一些奇怪的
    • 所以在ES6中新增了Reflect,让我们这些操作都集中到了Reflect对象上

Reflect的方法

Reflect中有13种方法,与Proxy一一对应

在这里插入图片描述


5. Proxy + Reflect配合使用

用Reflect替换代理对象捕获器中直接对原对象进行操作

const obj = {
  name: "xs",
  age: 18,
};

const objProxy = new Proxy(obj, {
  get(target, key, receiver) {
    // receiver永远指向 Proxy 本身或者继承它的对象
    return Reflect.get(target, key, receiver); // 语言内部获取,替代return target[key]
    // Reflect中的receiver可以改变计算属性中 this 的指向
  },

  set(target, key, newValue, receiver) {
    Reflect.set(target, key, newValue, receiver); //会返回一个布尔值,标志操作是否成功 替代target[key] = newValue
  },
});

objProxy.name = "kobe";
console.log(objProxy.name);

6. 总结

在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!关于"vue3proxy结合reflect"的问题,我理解你可能想了解如何在Vue 3使用Proxy与Reflect结合起来。Vue 3是一个流行的JavaScript框架,而Proxy和Reflect则是ES6新增的特性。 在Vue 3,可以使用Proxy对象来代理Vue实例,以便捕获对数据的访问和修改。Proxy对象可以拦截并处理对Vue实例的操作,比如读取、设置和删除属性等。而Reflect对象提供了一组用于操作对象的方法,比如Reflect.get()、Reflect.set()和Reflect.deleteProperty()等。 结合使用Proxy和Reflect可以提供更灵活的控制和监控能力。你可以通过在Vue实例上创建一个代理对象,来拦截对数据的访问和修改,并在代理处理器使用Reflect方法来操作实际的数据。这样可以轻松地实现对数据的拦截、校验、代理等功能。 下面是一个简单的示例代码,展示了如何在Vue 3使用Proxy和Reflect结合起来: ```javascript const data = { message: 'Hello, Vue!', }; const proxy = new Proxy(data, { get(target, key) { console.log('Getting ' + key); return Reflect.get(target, key); }, set(target, key, value) { console.log('Setting ' + key + ' to ' + value); return Reflect.set(target, key, value); }, }); // 创建Vue应用 const app = Vue.createApp({ data() { return proxy; // 使用代理对象 }, }); app.mount('#app'); ``` 在上面的代码,我们创建了一个名为data的普通对象,并使用Proxy对象创建了一个代理对象proxy。在代理对象的get和set处理器,我们分别使用Reflect.get和Reflect.set来操作实际的数据。这样,当我们通过Vue实例访问或修改数据时,会触发代理处理器,并通过Reflect方法操作实际的数据。 希望这个例子能帮助到你,如果还有其他问题,请随时提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值