Jansiel Notes

Js之Reflect

反射,什么是反射机制?

【Java的反射机制】是在编译阶段不知道是哪个类被加载,而是在运行的时候才加载、执行。
js中的apply就是反射机制。

Reflect简介

  • Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法,这些方法与处理器对象的方法相同。Reflect不是一个函数对象,因此它是不可构造的。
  • 与大多数全局对象不同,Reflect没有构造函数。你不能将其与一个new运算符一起使用,或者将Reflect对象作为一个函数来调用。Reflect的所有属性和方法都是静态的( 就像Math对象 )

为什么要用Reflect?

  • Reflect内部封装了一系列对对象的底层操作,Reflect成员方法就是Proxy处理对象的默认实现
    1const proxy = new Proxy(obj, {
    2    get(target, property) {
    3        // 如果没有定义get方法,那么默认返回的就是Reflect的get方法
    4        return Reflect.get(target, property)
    5    }
    6})
    
  • 为什么要用Reflect?
    • 因为Reflect提供了一套用于操作对象的API,我们之前操作对象可以用Object上面的一些方法,也可以用in、delete这种操作符,使用Reflect就统一了操作方式。

常见方法:

这些方法提供了一种更直观、一致的方式来执行与对象和属性相关的底层操作。它们通常比直接调用对象上的方法或使用操作符更具有灵活性和可读性。

  1. Reflect.get(target, propertyKey, [receiver]): 返回指定属性的值。
    • target:要读取属性的目标对象。
    • propertyKey:属性的键。
    • receiver(可选):如果提供,它将被视为 get 操作的 this 值。
    1const obj = { name: \'John\' };
    2const value = Reflect.get(obj, \'name\');
    3console.log(value); // \'John\'
    
  2. Reflect.set(target, propertyKey, value, [receiver]): 设置指定属性的值。
    • target:要设置属性的目标对象。
    • propertyKey:属性的键。
    • value:要设置的值。
    • receiver(可选):如果提供,它将被视为 set 操作的 this 值。
    1const obj = { name: \'John\' };
    2Reflect.set(obj, \'name\', \'Alice\');
    3console.log(obj.name); // \'Alice\'
    
  3. Reflect.has(target, propertyKey): 判断一个对象是否具有指定属性。
    • target:要检查的目标对象。
    • propertyKey:属性的键。
    1const obj = { name: \'John\' };
    2const hasName = Reflect.has(obj, \'name\');
    3console.log(hasName); // true
    
  4. Reflect.deleteProperty(target, propertyKey): 删除对象的指定属性。
    • target:要删除属性的目标对象。
    • propertyKey:属性的键。
    1const obj = { name: \'John\' };
    2Reflect.deleteProperty(obj, \'name\');
    3console.log(obj.name); // undefined
    
  5. Reflect.apply(target, thisArgument, argumentsList): 类似于 Function.prototype.apply` 方法,用于调用函数。
    • target:要调用的函数。
    • thisArgument:调用函数时的 this 值。
    • argumentsList:一个类数组对象,其中包含传递给函数的参数。
    1function greet(name) {
    2  return `Hello, ${name}!`;
    3}
    4
    5const result = Reflect.apply(greet, null, [\'John\']);
    6console.log(result); // \'Hello, John!\'
    7
    

底层操作

这些方法提供了对对象底层操作的一些高级控制和更灵活的使用方式。你可以根据需要选择适合你的场景的方法。

  1. Reflect.getProperty(target, propertyKey[, receiver])
    • 作用:获取目标对象上指定属性的值。
    • 参数:
      • target:目标对象。
      • propertyKey:属性的键。
      • receiver(可选):如果提供,它将被视为 get 操作的 this 值。
    1const obj = { name: \'John\' };
    2const value = Reflect.getProperty(obj, \'name\');
    3console.log(value); // \'John\'
    
  2. Reflect.setProperty(target, propertyKey, value[, receiver])
    • 作用:设置目标对象上指定属性的值。
    • 参数:
      • target:目标对象。
      • propertyKey:属性的键。
      • value:要设置的值。
      • receiver(可选):如果提供,它将被视为 set 操作的 this 值。
    1const obj = { name: \'John\' };
    2Reflect.setProperty(obj, \'name\', \'Alice\');
    3console.log(obj.name); // \'Alice\'
    
  3. Reflect.isExtensible(target)
    • 作用:判断目标对象是否可扩展。
    • 参数:
      • target:目标对象。
    1const obj = { name: \'John\' };
    2console.log(Reflect.isExtensible(obj)); // true
    3Reflect.preventExtensions(obj);
    4console.log(Reflect.isExtensible(obj)); // false
    
  4. Reflect.preventExtensions(target):
    • 作用:阻止目标对象被扩展。
    • 参数:
      • target:目标对象。
    1const obj = { name: \'John\' };
    2Reflect.preventExtensions(obj);
    3obj.newProperty = \'New Value\';
    4console.log(obj.newProperty); // undefined
    
  5. Reflect.getOwnPropertyDescriptor(target, propertyKey):
    • 作用:获取目标对象上指定属性的属性描述符。
    • 参数:
      • target:目标对象。
      • propertyKey:属性的键。
    1const obj = { name: \'John\' };
    2const descriptor = Reflect.getOwnPropertyDescriptor(obj, \'name\');
    3console.log(descriptor); // { value: \'John\', writable: true, enumerable: true, configurable: true }
    
  6. Reflect.defineProperty(target, propertyKey, attributes):
    • 作用:在目标对象上定义或修改一个属性。
    • 参数:
      • target:目标对象。
      • propertyKey:属性的键。
      • attributes:属性描述符对象。
    1const obj = {};
    2Reflect.defineProperty(obj, \'name\', { value: \'John\', writable: true });
    3console.log(obj.name); // \'John\'
    
  7. Reflect.ownKeys(target):
    • 作用:返回目标对象上可枚举和不可枚举的属性键。
    • 参数:
      -target:目标对象。
    1const obj = { name: \'John\', age: 25 };
    2const keys = Reflect.ownKeys(obj);
    3console.log(keys); // [\'name\', \'age\']
    
  8. Reflect.construct(target, argumentsList[, newTarget]):
    • 作用:类似于 new 操作符,用于创建一个实例。
    • 参数:
      • target:要调用的构造函数。
      • argumentsList:一个类数组对象,其中包含构造函数的参数。
      • newTarget(可选):如果提供,它将被视为构造函数的构造器。
    1class Example {
    2  constructor(value) {
    3    this.value = value;
    4  }
    5}
    6const instance = Reflect.construct(Example, [\'Hello\']);
    7console.log(instance.value); // \'Hello\'
    
  9. Reflect.preventExtensions(target):
    • 作用:阻止目标对象被扩展。
    • 参数:
      • target:目标对象。
    1const obj = { name: \'John\' };
    2Reflect.preventExtensions(obj);
    3
    4obj.newProperty = \'New Value\';
    5console.log(obj.newProperty); // undefined
    

Reflect API

默认调?	功能
函数 用法 能力
get Reflect.get() 获取对象身上某个属性的值
set Reflect.set() 在对象上设置属性
has Reflect.has() 判断一个对象是否存在某个属性
deleteProperty Reflect.deleteProperty() 删除对象上的属性
getProperty Reflect.getPrototypeOf() 获取指定对象原型的函数
setProperty Reflect.setPropertyOf() 设置或改变对象原型的函数
isExtensible Reflect.isExtensible() 判断一个对象是否可扩展 (即是否能够添加新的属性)
preventExtensions Reflect.preventExtensions() 阻止新属性添加到对象
getOwnPropertyDescriptor Reflect.getOwnPropertyDescriptor() 获取给定属性的属性描述符
defineProperty Reflect.defineProperty() 定义或修改一个对象的属性
ownKeys Reflect.ownKeys() 返回由目标对象自身的属性键组成的数组
apply Reflect.apply() 对一个函数进行调用操作,同时可以传入一个数组作为调用参数
construct Reflect.construct() 对构造函数进行 new 操作,实现创建类的实例
preventExtensions Reflect.preventExtensions() 阻止新属性添加到对象