代理和反射-Reflect(反射)

183 阅读2分钟

概述

代理和反射相辅相成。要理解代理,得先理解Reflect(反射)。

Reflect是什么?

Reflect是一个内置的js对象(以前没有,ES6才出来的,有兼容问题 ),它提供了一系列方法,可以让开发者通过调用这些方法,访问一些js底层功能。

由于它类似于其他语言的 反射,因此取名为Reflect。

Reflect可以做什么底层功能?

使用Reflect可以实现诸如 属性的赋值与取值、调用普通函数、调用构造函数、判断属性是否存在与对象中 等等功能。

这些功能不是已经存在了嘛?为什么还需要用Reflect实现一次?

有一个重要理念,在ES5就被提出:减少魔法,让代码更纯粹。(功能都以API的形式出现,而不是以特殊的语法来实现)

为什么提出这样的理念? 很大程度是受到函数式编程的影响。

函数式编程:一切都是API。 举例:函数式编程的写法

// 实现 3+1
add(3)(1)

// (3+1)*6
plus(add(3)(1))(6)

ES6进一步贯彻了这种理念,它认为,对属性内存的控制,原型链的修改、函数的调用等等,这些都属于底层实现,属于一种魔法,因此,需要将它们提取出来,形成一个正常的API,并高度聚合到某个对象中,于是,就造就了Reflect对象。

因此,你可以看到Reflect对象中有很多的API都可以使用过去的某种语法或其他API实现。

它里面到底提供了哪些API?

  • Reflect.set(target, propertyKey, value): 设置对象target的属性propertyKey的值为value,等同于给对象的属性赋值

    const obj = {
        a:1,
        b:2
    }
    
    // 魔法
    obj.a = 3;
    
    // Reflect写法
    Reflect.set(obj,'a',10)
    
  • Reflect.get(target, propertyKey): 读取对象target的属性propertyKey,等同于读取对象的属性值

    const obj = {
        a:1,
        b:2
    }
    // Reflect写法
    Reflect.get(obj,'a')
    
  • Reflect.apply(target, thisArgument, argumentsList):调用一个指定的函数,并绑定this和参数列表。等同于函数调用

     function method(a, b){
         console.log("method", a, b);
     }
    
    // 魔法调用
    method(3, 4);
    
    // Reflect调用
    Reflect.apply(method, null, [3, 4])
    
  • Reflect.deleteProperty(target, propertyKey):删除一个对象的属性

     const obj = {
         a: 1,
         b: 2
     }
    
    // 魔法删除
    delete obj.a;
    
    // Reflect删除
    Reflect.deleteProperty(obj, "a");
    
  • Reflect.defineProperty(target, propertyKey, attributes):类似于Object.defineProperty,不同的是如果配置出现问题,返回false而不是报错

  • Reflect.construct(target, argumentsList):用构造函数的方式创建一个对象

    function Test(a, b) {
        this.a = a;
        this.b = b;
    }
    
    // 魔法创建对象
    const t = new Test(1, 3);
    
    // Reflect创建
    const t = Reflect.construct(Test, [1, 3]);
    
  • Reflect.has(target, propertyKey): 判断一个对象是否拥有一个属性

    const obj = {
        a: 1,
        b: 2
    }
    
    // 魔法判断
    console.log("a" in obj);
    
    // Reflect判断 
    console.log(Reflect.has(obj, "a"));
    
  • 其他API