zoukankan      html  css  js  c++  java
  • ES6开发学习总结(二)—— Reflect与Proxy

    概述

    Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。

    Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。

    Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

    Proxy

    一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。

    eg:

    let target = {name:'king',age:27};
    
    let handler = {
        get: function(target, key) {
            console.log('getting '+key);
            return target[key]; // 不是target.key
        },
        set: function(target, key, value) {
            console.log('setting '+key);
            target[key] = value;
        }
    }
    
    let proxy = new Proxy(target,handler)
    
    proxy.name = "king"; 
        //getting name
        //"king"
    proxy.name = "kang"
        //setting name
        //"kang"     

    通过构造函数新建实例时其实是对目标对象进行了浅拷贝,因此目标对象与代理对象会互相

    // target 可以为空对象
    let targetEpt = {}
    let proxyEpt = new Proxy(targetEpt, handler) //上例的handler
    // 调用 get 方法,此时目标对象为空,没有 name 属性
    proxyEpt.name // getting name
    // 调用 set 方法,向目标对象中添加了 name 属性
    proxyEpt.name = 'Tom'
    // setting name
    // "Tom"
    // 再次调用 get ,此时已经存在 name 属性
    proxyEpt.name
    // getting name
    // "Tom"
     
    // 通过构造函数新建实例时其实是对目标对象进行了浅拷贝,因此目标对象与代理对象会互相

    Reflect

    ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上(当前某些方法会同时存在于 Object 和 Reflect 对象上),未来的新方法会只部署在 Reflect 对象上。

    Reflect 对象对某些方法的返回结果进行了修改,使其更合理。

    Reflect 对象使用函数的方式实现了 Object 的命令式操作。主要作用有:

    • 将Object对象的一些属于语言内部的方法放到Reflect对象上,从Reflect上能拿到语言内部的方法。如:Object.defineProperty
    • 修改某些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对象的方法与Proxy对象的方法一一对应,只要proxy对象上有的方法reflect也能找到。

    Reflect.defineProperty等同于Object.defineProperty,用来为对象定义属性。未来后者会被逐渐废除。

    function MyDate() {
      /**/
    }
    
    // 旧写法
    Object.defineProperty(MyDate, 'now', {
      value: () => Date.now()
    });
    
    // 新写法
    Reflect.defineProperty(MyDate, 'now', {
      value: () => Date.now()
    });

    如果第一个参数不是对象,就会抛出错误信息。

    该方法配合Proxy.defineProperty使用:

    const p = new Proxy({}, {
      defineProperty(target, prop, descriptor) {
        console.log(descriptor);
        return Reflect.defineProperty(target, prop, descriptor);
      }
    });
    
    p.foo = 'bar';
    // {value: "bar", writable: true, enumerable: true, configurable: true}
    
    p.foo // "bar"

    上面代码中,Proxy.defineProperty对属性赋值设置了拦截,Reflect.defineProperty完成了赋值。

    Reflect一共有13个静态方法

    Reflect.apply(target, thisArg, args)
    Reflect.construct(target, args)
    Reflect.get(target, name, receiver)
    Reflect.set(target, name, value, receiver)
    Reflect.defineProperty(target, name, desc)
    Reflect.deleteProperty(target, name)     
    Reflect.has(target, name)
    Reflect.ownKeys(target)
    Reflect.isExtensible(target)
    Reflect.preventExtensions(target)
    Reflect.getOwnPropertyDescriptor(target, name)
    Reflect.getPrototypeOf(target)
    Reflect.setPrototypeOf(target, prototype)

    上面这些方法的作用大部分与Object对象的同名方法都是相同的,与Proxy对象的方法一一对应的。

    eg:

    const myObj = { foo: 'bar' };
    
    // 旧写法
    delete myObj.foo;
    
    // 新写法
    Reflect.deleteProperty(myObj, 'foo');
  • 相关阅读:
    我今天能懂
    SpringMVC之RequestContextHolder分析
    idea只导入部分依赖
    idea中GitPush失败问题
    SpringBoot常用配置,引入外部配置文件信息,热加载
    idea的yml文件不识别问题
    SpringBoot介绍,快速入门小例子,目录结构,不同的启动方式,SpringBoot常用注解
    Java连接Redis,存储对象获取对象()byte和json),连接池
    Nginx的反向代理
    Nginx介绍,安装,配置
  • 原文地址:https://www.cnblogs.com/king-brook/p/14532173.html
Copyright © 2011-2022 走看看