• Reflect的使用


    Reflect的使用

    Reflect是一个内建的对象,用来提供方法去拦截JavaScript的操作。Reflect不是一个函数对象,所以它是不可构造的,也就是说它不是一个构造器,你不能通过new操作符去新建或者将其作为一个函数去调用Reflect对象。Reflect的所有属性和方法都是静态的。

    为什么需要Reflect

    Reflect对象最大的意义就是提供了一套统一操作ObjectAPI,因为在这之前操作对象时都会使用Object对象上的方法,也有可能使用像delete或者是in这样的操作符。

    Reflect对象就很好的解决了这样一个问题,他统一了对象的操作方式,我们可以通过几个简单的例子来看一下。

    这里我们先定义一个obj对象,然后在对象当中定义了几个属性。按照传统的方式如果我们需要判断这个对象中是否存在某个属性,我们需要使用in这个语句,用到in操作符,删除属性需要使用到delete语句。而如果需要获取对象中所有的属性名,那需要使用Object.keys这样的方法。

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    console.log('a' in obj);            // true
    console.log(delete obj['a']);       // true
    console.log(Object.keys(obj));      // ["b", "c"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    那也就是说我们同样都是去操作这个对象,但是我们一会需要用操作符的方式,一会又需要用到某一个对象当中的方法。

    Reflect就提供了一个统一的方式,当判断对象当中是否存在某一个属性可以使用Reflect.has方法。

    console.log(Reflect.has(obj, 'b'));              // true
    console.log(Reflect.deleteProperty(obj, 'b'));   // true
    console.log(Reflect.ownKeys(obj));               // ["c"]
    
    • 1
    • 2
    • 3

    Reflect对象的方法

    Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为。

    1. get

    Reflect.get方法与从对象 (target[propertyKey]) 中读取属性类似,但它是通过一个函数执行来操作的。

    Reflect.get(target, propertyKey[, receiver])
    
    • 1

    接收3个参数:

    • target: 目标对象, 如果不是对象,会报错
    • propertyKey: 属性名
    • receiver: 如果target对象中指定了getterreceiver则为getter调用时的this值。
    const obj = {
      a: 1,
      b: 2,
      get c() {
        return this.a + this.b;
      }
    }
    
    const obj2 = {
      a: 4,
      b: 5
    }
    
    const arr = [1, '2', 'string'];
    
    Reflect.get(obj, 'a')          // 1
    Reflect.get(arr, 2)            // "string"
    
    // c的getter中的this指向obj2
    Reflect.get(obj, 'c', obj2)    // 9
    
    Reflect.get(1, 'a');           // Uncaught TypeError: Reflect.get called on non-object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2. set

    在对象上设置一个属性。

    Reflect.set(target, propertyKey, value[, receiver])
    
    • 1

    接收4个参数:

    • target: 目标对象, 如果不是对象,会报错
    • propertyKey: 属性名
    • value: 值
    • receiver: 如果target对象中指定了setterreceiver则为setter调用时的this值。
    const obj = {
      a: 1,
      set b(value) {
        return this.a = value;
      }
    }
    
    const obj2 = {
      a: 4
    }
    
    Reflect.set(obj, 'c', 3);          // true
    obj.c                              // 3
    Reflect.set(obj, 'b', 2)           // true
    obj.a                              // 2
    Reflect.set(obj, 'b', 2, obj2);    // true
    obj2.a                             // 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. apply

    apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数。

    一般来说,如果要绑定一个函数的this对象,可以这样写fn.apply(obj, args),但是如果函数定义了自己的apply方法,就只能写成Function.prototype.apply.call(fn, obj, args),采用Reflect对象可以简化这种操作。

    Reflect.apply(target, thisArgument, argumentsList)
    
    • 1

    接收3个参数:

    • target: 目标函数
    • thisArgument: 需要绑定的this对象
    • argumentsList: 传入的参数列表(类数组对象)
    const ages = [11, 33, 12, 54, 18, 96];
    
    // 旧写法
    const youngest = Math.min.apply(Math, ages);
    const oldest = Math.max.apply(Math, ages);
    const type = Object.prototype.toString.call(youngest);
    
    // 新写法
    const youngest = Reflect.apply(Math.min, Math, ages);
    const oldest = Reflect.apply(Math.max, Math, ages);
    const type = Reflect.apply(Object.prototype.toString, youngest, []);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4. has

    has 作用与 in 操作符相同。

    Reflect.has(target, propertyKey)
    
    • 1

    接收2个参数

    • target: 目标对象,非Object类型会报错
    • propertyKey: 属性名
    const obj = {
      a: 1,
    }
    
    'a' in obj                 // true
    
    Reflect.has(obj, 'a')      // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7. defineProperty

    defineProperty基本等同于 Object.defineProperty()方法,唯一不同是返回 Boolean 值。

    Reflect.defineProperty(target, propertyKey, attributes)
    
    • 1

    接收3个参数:

    • target: 目标对象,非Object类型会报错
    • propertyKey: 要定义或修改的属性的名称
    • attributes: 要定义或修改的属性的描述。
    const obj = {};
    Reflect.defineProperty(obj, 'a', {value: 1})    // true
    obj.a                                           // 1
    
    • 1
    • 2
    • 3

    8. getOwnPropertyDescriptor

    getOwnPropertyDescriptorObject.getOwnPropertyDescriptor、 方法相似。如果在对象中存在,则返回给定的属性的属性描述符。否则返回 undefined

    Reflect.getOwnPropertyDescriptor(target, propertyKey)
    
    • 1

    接收2个参数:

    • target: 目标对象,非Object类型会报错
    • propertyKey: 属性名
    var obj = {};
    Object.defineProperty(obj, 'a', {
      value: 1,
      enumerable: false,
    });
    
    Object.getOwnPropertyDescriptor(obj, 'a');
    
    Reflect.getOwnPropertyDescriptor(obj, 'a');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    9. getPrototypeOf

    getPrototypeOfObject.getPrototypeOf 方法几乎是一样的。都是返回指定对象的原型。

    Reflect.getPrototypeOf(target)
    
    • 1

    接收1个参数

    • target: 目标对象,非Object类型会报错
    Reflect.getPrototypeOf({}); // Object.prototype
    Reflect.getPrototypeOf(Object.prototype); // null
    Reflect.getPrototypeOf(Object.create(null)); // null
    
    • 1
    • 2
    • 3

    10. isExtensible

    isExtensible判断一个对象是否可扩展(即是否能够添加新的属性)

    Reflect.isExtensible(target)
    
    • 1

    接收1个参数

    • target: 目标对象,非Object类型会报错
    const obj = {};
    
    Object.isExtensible(obj)  // true
    
    Reflect.isExtensible(obj) // true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如果参数不是对象,Object.isExtensible会返回false,因为非对象本来就是不可扩展的,而Reflect.isExtensible会报错。

    11. ownKeys

    ownKeys 返回一个由目标对象自身的属性键组成的数组。

    Reflect.ownKeys(target)
    
    • 1

    接收1个参数

    • target: 目标对象,非Object类型会报错

    12. preventExtensions

    preventExtensions 方法阻止新属性添加到对象 (例如:防止将来对对象的扩展被添加到对象中)。

    Reflect.preventExtensions(target)
    
    • 1

    接收1个参数

    • target: 目标对象,非Object类型会报错
    const obj = {};
    
    Object.preventExtensions(obj)  // obj {}
    
    Reflect.preventExtensions(obj) // true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    13. setPrototypeOf

    setPrototypeOfObject.setPrototypeOf 方法是一样的。它可设置对象的原型(即内部的 [[Prototype]] 属性)为另一个对象或 null,如果操作成功返回 true,否则返回 false

    Reflect.setPrototypeOf(target, prototype)
    
    • 1

    接收2个参数

    • target: 目标对象,非Object类型会报错
    • prototype: 对象的新原型(一个对象或 null
    const obj = {};
    
    Object.setPrototypeOf(obj, Array.prototype);
    
    Reflect.setPrototypeOf(obj, Array.prototype);
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Fiddler弱网测试
    竣达技术 | 适用于”日月元”品牌UPS微信云监控卡
    ARM开发(5)ARM的接口技术(串行通信与并行通信,同步串行通信与异步串行通信,波特率,串行通信术语,uart,i2c,spi三种协议简单引入)
    [Linux]套接字通信
    电容笔好还是触屏笔好?便宜又好用的电容笔推荐
    机器学习算法 —— 决策树
    基于 SpringBoot + FreeMarker 开发的博客论坛项目
    Intel汇编-系统调用返回值
    【MongoDB】索引 – 文本索引(指定语言)
    异地寄件教程分析
  • 原文地址:https://blog.csdn.net/qq_42880714/article/details/125550528