Es6 元编程,Proxy(代理)和Reflect(反射)

Reflect对象与Proxy对象一样,都是 ES6 为了操作对象而提供的新 API

1、Reflect

  • Reflect(反射)的设计目的:

    • 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。也就是说,从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)让它们变成了函数行为。

    • 配合Proxy(代理)对象,完成代理对象修改源对象的默认行为。Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法

  • Reflect 对象的静态方法

    • Reflect.get(target, name, receiver)
      Reflect.get方法查找并返回target对象的name属性,如果没有该属性,则返回undefined。
    • Reflect.set(target, name, value, receiver)
      Reflect.set方法设置target对象的name属性等于value
    • Reflect.has(target, name)
      Reflect.has方法对应name in obj里面的in运算符。
    • Reflect.deleteProperty(target, name)
      Reflect.deleteProperty方法等同于delete obj[name],用于删除对象的属性。
    • Reflect.construct(target, args)
      Reflect.construct方法等同于new target(…args),这提供了一种不使用new,来调用构造函数的方法。
    • Reflect.getPrototypeOf(target)
      Reflect.getPrototypeOf方法用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj)。
    • Reflect.setPrototypeOf(target, prototype)
      Reflect.setPrototypeOf方法用于设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)方法。它返回一个布尔值,表示是否设置成功。
    • Reflect.apply(target, thisArg, args)
      Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数。
    • Reflect.defineProperty(target, name, desc)
      Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty代替它。
    • Reflect.getOwnPropertyDescriptor(target, name)
      Reflect.getOwnPropertyDescriptor基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象,将来会替代掉后者。
    • Reflect.isExtensible(target)
      Reflect.isExtensible方法对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。
    • Reflect.preventExtensions(target)
      Reflect.preventExtensions对应Object.preventExtensions方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。
    • Reflect.ownKeys(target)
      Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。

2、Proxy

  • Proxy(代理)的设计目的

    • 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。可以理解为,对目标对象(target)创建了一个代理对象(proxy),对该目标对象(target)的访问,都需要先通过代理对象(proxy)进行拦截,在代理对象中可以对外界的访问操作进行过滤和处理。
    • ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
    • 如果handler没有设置任何拦截,那就等同于直接通向原对象。
    • 在拦截中可以通过Reflect(反射)将操作通向原对象
    • 例如:Proxy 对象定义了一个目标(这里是一个空对象)和一个实现了 get 陷阱的 handler 对象。这里,代理的对象在获取未定义的属性时不会返回 undefined,而是返回 42。
      let handler = {
        //Proxy 对象的get陷阱
        get: function(target, name,receiver){
        	if(name in target){
        		//存在指定的属性,直接通过Reflect将操作通向目标对象的
        		return Reflect.get(target, name, receiver);
        	}
        	//没有指定的属性,总是返回42
        	return  42;
         }
      };
      
      //为目标对象(这里是空对象),句柄handler对象用来定制拦截行为
      let targetObj = {};
      let p = new Proxy(targetObj, handler);
      //必须通过Proxy的实例对象进行操作才起作用(直接操作targetObj时Proxy是没有作用的)
      //访问p的a属性,是进入了Proxy定义的get陷阱
      p.a = 1;
      
      console.log(p.a, p.b); // 1, 42
      
  • Proxy 对象可用的陷阱(拦截)

    • get(target, propKey, receiver)
      拦截对象属性的读取,比如proxy.foo和proxy[‘foo’]。
    • set(target, propKey, value, receiver)
      拦截对象属性的设置,比如proxy.foo = v或proxy[‘foo’] = v,返回一个布尔值。
    • has(target, propKey)
      拦截propKey in proxy的操作,返回一个布尔值。
    • deleteProperty(target, propKey)
      拦截delete proxy[propKey]的操作,返回一个布尔值。
    • ownKeys(target)
      拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
    • getOwnPropertyDescriptor(target, propKey)
      拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
    • defineProperty(target, propKey, propDesc)
      拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
    • preventExtensions(target)
      拦截Object.preventExtensions(proxy),返回一个布尔值。
    • getPrototypeOf(target)
      拦截Object.getPrototypeOf(proxy),返回一个对象。
    • isExtensible(target)
      拦截Object.isExtensible(proxy),返回一个布尔值。
    • setPrototypeOf(target, proto)
      拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
    • apply(target, object, args)
      拦截 Proxy 实例作为函数调用的操作,比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…)。
    • construct(target, args)
      拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。

    参考:
    一文带你彻底搞懂Proxy和Reflect!
    元编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值