极简三分钟ES6 - 反射Reflect

74 阅读2分钟

定义Reflect

想象我们有一把 万能工具箱🔧,Reflect 就是 JavaScript 提供的操作对象的标准化工具集。它把原先散落在各处的底层操作(如属性读写、函数调用等)统一封装成 13 个静态方法,让代码更规范、更安全

为什么需要使用Reflect

1. 解决历史问题

  • 旧语法不一致 obj.key (属性读)、obj.key = 1(属性写)、delete obj.key (删除)等操作语法各异
  • 错误处理混乱
    Object.defineProperty() 失败会抛错,而 delete 失败只是返回 false

2. 统一操作规范

Reflect 将所有对象操作转化为方法调用,提供一致的返回值(成功 true/失败 false

// 旧方式 
delete obj.name;  // 语法特殊,返回值不明确
 
// Reflect 方式 
Reflect.deleteProperty(obj,  "name"); // 明确返回 true/false

一些常见的使用场景

属性操作:替代点运算符

场景传统方式Reflect 方式
读取属性obj.keyReflect.get(obj, "key")
设置属性obj.key=1Reflect.set(obj, "key", 1)
删除属性delete keyReflect.deleteProperty(obj, "key")
检查属性是否存在"key" in objReflect.has(obj, "key")

优势

  • 避免语法魔法,所有操作都是函数调用
  • 支持 Receiver 参数(可绑定 this 指向)

函数与构造函数调用

// 调用函数 
func(1, 2);  
Reflect.apply(func,  thisArg, [1, 2]); // 绑定 this 和参数
 
// 构造函数调用
new Person("Alice");  
Reflect.construct(Person,  ["Alice"]); // 动态创建实例 

适用场景:需要动态控制 this 或批量传参时

对象扩展与原型控制

// 冻结对象扩展 
Object.preventExtensions(obj);   
Reflect.preventExtensions(obj);  // 返回操作结果 true/false 
 
// 获取/设置原型
Reflect.getPrototypeOf(obj);   
Reflect.setPrototypeOf(obj,  newProto);  

优势:操作失败时返回 false(旧方法会抛错),更安全

与 Proxy 的黄金组合

Reflect 常与 Proxy 代理对象 配合使用,在代理陷阱中调用默认行为

const proxy = new Proxy(obj, {
  get(target, key) {
    console.log(` 读取 ${key}`);
    return Reflect.get(...arguments);  // 调用默认的 get 行为 
  }
});

关键作用

  • 代理陷阱中无需手动实现底层逻辑
  • 保持原始行为的正确性(如原型链访问)

Reflect vs Object 方法

特性ReflectObject 方法
返回值统一返回布尔值/结果可能抛错(如 defineProperty)
函数化所有操作是静态方法混合语法(如 key in obj
错误处理安全返回 false可能中断执行
与 Proxy 协作⭐⭐⭐ 无缝配合❌ 需手动实现

牢记

“Reflect 是对象的瑞士军刀——把零散的工具收进标准工具箱,让代码更规整、更可控。”