ES6-补充篇_Reflect和proxy

在这里插入图片描述

简介

本篇文章只是为了补充一些遗漏的技术点,望大家批评多多指教

1.Proxy

proxy的字面意思的理解就是代理

用于定义基本操作的自定义行为,就是我们可以自定义某些行为,比如属性的查找,赋值,枚举,函数调用等。

实际上我们利用这个Proxy实现对编程语言进行编程,就是把一些内部的方式,内置的方法改变了,

这种编程就叫做语言编程。属性代理就做拦截。关于Proxy需要注意的地方有:Proxy内部的this关键字的指向是Proxy代理本身;

它的构建方式需要借助一个Proxy的构造函数new Proxy(target,handler),

其中target叫做目标对象,Proxy构造函数返回的是一个包装过后的目标对象,handler是代理的行为的函数。
基本用法:

let pro = new Proxy(target,handler);

new Proxy()表示生成一个Proxy实例

target参数表示所要拦截的目标对象

handler参数也是一个对象,用来定制拦截行为。

Proxy支持13种拦截行为(handle),简单介绍下其中2种拦截行为,

get

get(target, propKey, receiver)

用于拦截某个属性的读取操作,可以接受三个参数:

target:目标对象

propKey:属性名

receiver(可选):proxy 实例本身(严格地说,是操作行为所针对的对象)

举例:

	let target = {
    x: 10,
    y: 20
};
​
let hanler = {
    get: (obj, prop) => 42
};
​
target = new Proxy(target, hanler);
​
target.x; //42
target.y; //42
target.x; // 42

解析:
	结果是一个对象将为任何属性访问操作都返回“42”。 
	这包括target.x,target['x'],Reflect.get(target, 'x')等。

set

set(target, propKey, value, receiver)

用于拦截某个属性的赋值操作,可以接受四个参数:

target:目标对象
propKey:属性名
value:属性值
receiver(可选):Proxy 实例本身

let hero = {
  name: "赵云",
  age: 25
}

let handler = {
  get: (hero, name, ) => {
    const heroName =`英雄名是${hero.name}`;
    return heroName;
  },
  set:(hero,name,value)=>{
    console.log(`${hero.name} change to ${value}`);
    hero[name] = value;
    return true;
  }
}

let heroProxy = new Proxy(hero, handler);

console.log(heroProxy.name);
heroProxy.name = '黄忠';
console.log(heroProxy.name);

// --> 英雄名是赵云

// --> 赵云 change to 黄忠

// --> 英雄名是黄忠

解析:
	创建hero对象为所要拦截的对象;
	
	handler对象为拦截对象后执行的操作,这里get方法为读取操作,
	
	即用户想要读取heroProxy中的属性时执行的拦截操作。
	
	最后创建一个Proxy实例,当读取heroProxy中的属性时,
	
	结果打印出来的总是“黄忠”字符串。
下面是 Proxy 支持的拦截操作一览,一共 13 种。
1、get(target, prop, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。

2、set(target, prop, value, receiver):拦截对象属性的设置,最后返回一个布尔值。

3、apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,
	比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。

4、construct(target, args):方法用于拦截 new 操作符,比如 new proxy()。
为了使 new操作符在生成的Proxy对象上生效,
用于初始化代理的目标对象自身必须具有 [[Construct]] 内部方法(即 new target 必须是有效的)。

5、has(target, prop): 判断对象是否有该属性  例如 prop in proxy的操作,返回一个布尔值。

6、deleteProperty(target, prop):拦截  delete proxy[prop] 的操作,返回一个布尔值。

7、ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、
	Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。
	该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。

8、getOwnPropertyDescriptor(target, prop):拦截 Object.getOwnPropertyDescriptor(proxy, propKey),
返回属性的描述对象。

9、defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、
Object.defineProperties(proxy, propDescs),返回一个布尔值。。

10、preventExtensions(target):拦截 Object.preventExtensions(proxy),返回一个布尔值。

11、getPrototypeOf(target):拦截 Object.getPrototypeOf(proxy),返回一个对象。

12、isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。

13、setPrototypeOf(target, proto):拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。
如果目标对象是函数,那么还有两种额外操作可以拦截。

Proxy vs Object.defineProperty
在 Proxy 出现之前,JavaScript 中就提供过 Object.defineProperty,
允许对对象的 getter/setter 进行拦截,那么两者的区别在哪里呢?

1、Object.defineProperty 不能监听所有属性
   Object.defineProperty 无法一次性监听对象所有属性,必须遍历或者递归来实现。
   
2、Object.defineProperty 无法监听新增加的属性
   Proxy 可以监听到新增加的属性,而 Object.defineProperty 不可以,
   需要你手动再去做一次监听。因此,在 Vue 中想动态监听属性,
    一般用 Vue.set(girl, "hobby", "game") 这种形式来添加。

3、Object.defineProperty 无法响应数组操作
   Object.defineProperty 可以监听数组的变化,
   Object.defineProperty 无法对 push、shift、pop、unshift 等方法进行响应

4、Proxy 拦截方式更多
	Proxy 提供了13种拦截方法,包括拦截 constructor、apply、deleteProperty 等等,
	而 Object.defineProperty 只有 get 和 set。

5. Object.defineProperty 兼容性更好
	Proxy 是新出的 API,兼容性还不够好,不支持 IE 全系列。

ES6中的Reflect

前言

我们来学习一下ES6的Reflect这个全局对象;首先我们要了解一下,为什么会新添加这么一个全局对象?如果你看过Reflect的一些函数,

你就会发现,这个对象上的方法基本上都可以从Object上面找到,找不到的那些,

也是可以通过对对象命令式的操作去实现的;那么为什么还要新添加一个呢?

Reflect介绍

1:Reflect上面的一些方法并不是专门为对象设计的,比如Reflect.apply方法,
	它的参数是一个函数,如果使用Object.apply(func)会让人感觉很奇怪。
	
2:用一个单一的全局对象去存储这些方法,能够保持其它的JavaScript代码的整洁、干净。不然的话,
	这些方法可能是全局的,或者要通过原型来调用。
	
3:将一些命令式的操作如delete,in等使用函数来替代,
	这样做的目的是为了让代码更加好维护,更容易向下兼容;也避免出现更多的保留字。
	
4:Reflect正是ES6 为了操作对象而提供的新 API。
      Reflect的本质其实就是建立起一套统一的API,便于新手学习和理解

基本特点

只要Proxy对象具有的代理方法,Reflect对象全部具有,以静态方法的形式存在。这些方法能够执行默认行为,
无论Proxy怎么修改默认行为,总是可以通过Reflect对应的方法获取默认行为。

修改某些Object方法的返回结果,让其变得更合理。比如,
Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,
而Reflect.defineProperty(obj, name, desc)则会返回false。让Object操作都变成函数行为。

某些Object操作是命令式,比如name in obj和delete obj[name],
而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)

让它们变成了函数行为。

下面我们来学习一下Reflect这个全局的对象,Reflect对象有下面这些静态的方法:

Reflect.apply

Reflect.construct

Reflect.defineProperty

Reflect.deleteProperty

Reflect.enumerate // 已废弃

Reflect.get

Reflect.getOwnPropertyDescriptor

Reflect.getPrototypeOf

Reflect.has

Reflect.isExtensible

Reflect.ownKeys

Reflect.preventExtensions

Reflect.set

Reflect.setPrototypeOf
举例

Reflect.get(target, name, receiver)

const { log } = console;

let myObject = {
    foo: 1,
    bar: 2,
    get baz() {
        return this.foo + this.bar;
    },
}
log(Reflect.get(myObject, 'foo')) // 1

log(Reflect.get(myObject, 'bar')) // 2

log(Reflect.get(myObject, 'baz')) // 3

如果name属性部署了读取函数(getter),则读取函数的this绑定receiver。

let myObject = {
    foo: 1,
    bar: 2,
    get baz() {
        return this.foo + this.bar;
    },
};

var myReceiverObject = {
    foo: 4,
    bar: 4,
};

// 8
log(Reflect.get(myObject, 'baz', myReceiverObject))

如果第一个参数不是对象,Reflect.get方法会报错。

Reflect.get(1, 'foo') // 报错

Reflect.get(false, 'foo') // 报错
Reflect.set(target, name, value, receiver)
Reflect.set方法设置target对象的name属性等于value。

let myObject = {
    foo: 1,
    set bar(value) {
        return this.foo = value;
    },
}

log(myObject.foo) // 1

Reflect.set(myObject, 'foo', 2);
log(myObject.foo) // 2

Reflect.set(myObject, 'bar', 3)
log(myObject.foo) // 3
Reflect.has(obj, name)
Reflect.has方法对应name in obj里面的in运算符。

let myObject = {
    foo: 1,
};

// 旧写法
'foo' in myObject // true

// 新写法
log(Reflect.has(myObject, 'foo')) // true

如果Reflect.has()方法的第一个参数不是对象,会报错。
Reflect.deleteProperty(obj, name)
Reflect.deleteProperty方法等同于delete obj[name],用于删除对象的属性。

const myObj = { foo: 'bar' };

// 旧写法
delete myObj.foo;

// 新写法
Reflect.deleteProperty(myObj, 'foo');

该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,
返回true;删除失败,被删除的属性依然存在,返回false。

如果Reflect.deleteProperty()方法的第一个参数不是对象,会报错。

以上仅仅是三个例子,希望可以帮助大家,谢谢观看!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!关于"vue3proxy结合reflect"的问题,我理解你可能想了解如何在Vue 3中使用ProxyReflect结合起来。Vue 3是一个流行的JavaScript框架,而ProxyReflect则是ES6中新增的特性。 在Vue 3中,可以使用Proxy对象来代理Vue实例,以便捕获对数据的访问和修改。Proxy对象可以拦截并处理对Vue实例的操作,比如读取、设置和删除属性等。而Reflect对象提供了一组用于操作对象的方法,比如Reflect.get()、Reflect.set()和Reflect.deleteProperty()等。 结合使用ProxyReflect可以提供更灵活的控制和监控能力。你可以通过在Vue实例上创建一个代理对象,来拦截对数据的访问和修改,并在代理处理器中使用Reflect方法来操作实际的数据。这样可以轻松地实现对数据的拦截、校验、代理等功能。 下面是一个简单的示例代码,展示了如何在Vue 3中使用ProxyReflect结合起来: ```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、付费专栏及课程。

余额充值