无需登录 数据私有 本地保存

Reflect API 使用浏览器 - 对象操作方法速查与测试

11
0
0
0

交互式 Reflect API 速查与测试工具 — 选择方法,编辑参数,实时查看执行结果与等效代码。 Reflect 是 ES6 内置对象,提供与 Proxy handler 一一对应的静态方法,让对象操作更规范、更函数式。

方法目录 13 个方法
属性操作
属性定义
原型操作
扩展控制
函数操作
测试台 Reflect.get
预设对象: 👤 用户对象 📦 嵌套对象 📋 数组 ⚡ 函数
等待执行...
// 选择方法后点击"执行测试"查看等效代码
Reflect 方法速查表
方法 返回值 等效传统操作 说明
Reflect.get(target, key[, receiver])anytarget[key]获取属性值,支持 receiver 代理
Reflect.set(target, key, value[, receiver])Booleantarget[key] = value设置属性值,返回是否成功
Reflect.has(target, key)Booleankey in target检查属性是否存在(含原型链)
Reflect.deleteProperty(target, key)Booleandelete target[key]删除属性,返回是否成功
Reflect.defineProperty(target, key, desc)BooleanObject.defineProperty()定义属性,失败返回 false(而非抛错)
Reflect.getOwnPropertyDescriptor(target, key)Object|nullObject.getOwnPropertyDescriptor()获取自有属性的描述符
Reflect.ownKeys(target)ArrayObject.getOwnPropertyNames() + Symbol返回所有自有键(含 Symbol)
Reflect.getPrototypeOf(target)ObjectObject.getPrototypeOf()获取原型对象
Reflect.setPrototypeOf(target, proto)BooleanObject.setPrototypeOf()设置原型,返回是否成功
Reflect.isExtensible(target)BooleanObject.isExtensible()检查对象是否可扩展
Reflect.preventExtensions(target)BooleanObject.preventExtensions()阻止扩展,返回是否成功
Reflect.apply(fn, thisArg, args)anyfn.apply(thisArg, args)函数式调用,更安全
Reflect.construct(ctor, args[, newTarget])Objectnew ctor(...args)构造实例,支持 newTarget
常见问题与知识点

Reflect 是 ES6(ECMAScript 2015)引入的内置对象(非构造函数),提供了一组静态方法用于操作对象。

它的设计目标:

  • 统一 API:将分散在 ObjectFunction 上的操作集中到一个命名空间。
  • 函数式风格:所有方法返回有意义的值(如 Reflect.set() 返回 Boolean),而非抛出异常。
  • 与 Proxy 互补:Reflect 的方法与 Proxy handler 一一对应,在 Proxy 中使用 Reflect 可以优雅地转发默认行为。
  • 更可靠:例如 Reflect.apply()Function.prototype.apply() 更安全(不会被篡改)。

特性ReflectObject
风格函数式,返回成功/失败命令式,失败时抛异常
defineProperty返回 Boolean成功返回对象/失败抛 TypeError
setPrototypeOf返回 Boolean失败抛 TypeError
preventExtensions返回 Boolean返回目标对象
ownKeys返回所有键(含 Symbol)需组合 getOwnPropertyNames + getOwnPropertySymbols
apply/construct提供函数式调用方式无对应方法

Proxy 的 handler 方法与 Reflect 方法一一对应,最佳实践是在 Proxy 中使用 Reflect 转发默认操作:

const handler = {
  get(target, key, receiver) {
    console.log(`读取: ${String(key)}`);
    return Reflect.get(target, key, receiver); // 转发默认行为
  },
  set(target, key, value, receiver) {
    console.log(`设置: ${String(key)} = ${value}`);
    return Reflect.set(target, key, value, receiver);
  }
};
const proxy = new Proxy({}, handler);

使用 receiver 参数可以正确处理 getter/setter 中的 this 指向。

Reflect.set(target, key, value, receiver)target[key] = value 的主要区别:

  • 返回值:Reflect.set 返回 Boolean 表示是否成功,直接赋值总是返回赋的值。
  • receiver 参数:当目标属性有 setter 时,receiver 作为 setter 中的 this,这在 Proxy 场景中至关重要。
  • 严格模式:直接赋值在严格模式下失败会抛 TypeError,Reflect.set 只是返回 false。

Reflect.ownKeys(target) 返回目标对象的所有自有键,包括:

  • 字符串键(可枚举 + 不可枚举)
  • Symbol 键

对比:

  • Object.keys():仅返回可枚举的字符串键
  • Object.getOwnPropertyNames():返回所有字符串键(含不可枚举),但不含 Symbol。
  • Object.getOwnPropertySymbols():仅返回 Symbol 键。
  • Reflect.ownKeys()以上三者的并集,等同于 [...Object.getOwnPropertyNames(target), ...Object.getOwnPropertySymbols(target)]

Reflect.apply(fn, thisArg, args) 更安全:

  • fn.apply 可能被覆盖或修改(如果 fn 上有同名属性)。
  • Function.prototype.apply 也可能被篡改。
  • Reflect.apply() 直接调用底层操作,无法被拦截或篡改。

语法更清晰:Reflect.apply(Math.max, null, [1, 2, 3]) 返回 3

Reflect API 在所有现代浏览器中完全支持

  • Chrome 49+
  • Firefox 42+
  • Safari 10+
  • Edge 12+
  • Node.js 6+

IE 11 及以下不支持。如果需兼容老旧浏览器,可使用 es6-shim 等 polyfill。对于绝大多数现代 Web 应用,Reflect API 可以放心使用。

Object.defineProperty() 在失败时(如不可扩展对象)会抛出 TypeError,需要用 try-catch 包裹。

Reflect.defineProperty() 只是返回 false,让错误处理更简洁:

// Object 方式 — 需要 try-catch
try {
  Object.defineProperty(obj, 'x', { value: 1 });
} catch (e) { /* 处理错误 */ }

// Reflect 方式 — 更优雅
if (!Reflect.defineProperty(obj, 'x', { value: 1 })) {
  // 处理失败
}