Reflect 是 ES6 引入的一个内置对象,它提供了一组用于操作对象的静态方法。这些方法与对象的默认行为相对应,让元编程变得更加简洁和统一。
Reflect 的设计目标
1. 将语言内部方法函数化
将一些原本只能通过操作符完成的操作提供为函数形式:
// 传统方式
delete obj.prop
'prop' in obj
// Reflect 方式
Reflect.deleteProperty(obj, 'prop')
Reflect.has(obj, 'prop')2. 与 Proxy 配合使用
Reflect 的方法与 Proxy 的拦截方法一一对应:
const handler = {
get(target, prop, receiver) {
console.log(`Getting ${prop}`)
return Reflect.get(target, prop, receiver) // 调用默认行为
},
set(target, prop, value, receiver) {
console.log(`Setting ${prop} = ${value}`)
return Reflect.set(target, prop, value, receiver)
}
}
const proxy = new Proxy({}, handler)3. 更合理的返回值
提供布尔值返回而不是抛出异常:
// Object.defineProperty 失败时抛出异常
try {
Object.defineProperty(obj, 'prop', descriptor)
} catch (e) {
// 处理错误
}
// Reflect.defineProperty 返回布尔值
if (Reflect.defineProperty(obj, 'prop', descriptor)) {
// 成功
} else {
// 失败
}主要方法详解
属性操作
const obj = { name: 'Vue', version: 3 }
// 获取属性
Reflect.get(obj, 'name') // 'Vue'
// 设置属性
Reflect.set(obj, 'author', 'Evan You') // true
// 检查属性存在
Reflect.has(obj, 'name') // true
// 删除属性
Reflect.deleteProperty(obj, 'version') // true
// 获取所有属性键
Reflect.ownKeys(obj) // ['name', 'author']属性描述符操作
const obj = {}
// 定义属性
Reflect.defineProperty(obj, 'prop', {
value: 42,
writable: true,
enumerable: true,
configurable: true
}) // true
// 获取属性描述符
Reflect.getOwnPropertyDescriptor(obj, 'prop')
// { value: 42, writable: true, enumerable: true, configurable: true }原型操作
const obj = {}
const proto = { inherited: true }
// 设置原型
Reflect.setPrototypeOf(obj, proto) // true
// 获取原型
Reflect.getPrototypeOf(obj) === proto // true对象扩展性
const obj = {}
// 检查是否可扩展
Reflect.isExtensible(obj) // true
// 阻止扩展
Reflect.preventExtensions(obj) // true
Reflect.isExtensible(obj) // false函数调用和构造
function greet(name) {
return `Hello, ${name}!`
}
// 调用函数
Reflect.apply(greet, null, ['World']) // 'Hello, World!'
// 构造对象
function Person(name) {
this.name = name
}
const person = Reflect.construct(Person, ['Alice'])
// 等同于 new Person('Alice')实际应用场景
1. 创建安全的属性访问
function safeGet(obj, prop) {
try {
return Reflect.get(obj, prop)
} catch (e) {
return undefined
}
}2. 实现观察者模式
function createObservable(target) {
const observers = new Set()
return new Proxy(target, {
set(obj, prop, value, receiver) {
const result = Reflect.set(obj, prop, value, receiver)
if (result) {
observers.forEach(observer => observer(prop, value))
}
return result
},
addObserver(observer) {
observers.add(observer)
}
})
}3. 属性验证
function createValidatedObject(target, validators = {}) {
return new Proxy(target, {
set(obj, prop, value, receiver) {
const validator = validators[prop]
if (validator && !validator(value)) {
throw new Error(`Invalid value for ${prop}`)
}
return Reflect.set(obj, prop, value, receiver)
}
})
}
const user = createValidatedObject({}, {
age: value => typeof value === 'number' && value >= 0
})
user.age = 25 // 成功
user.age = -5 // 抛出错误Reflect vs Object 方法对比
| Reflect | Object | 区别 |
|---|---|---|
Reflect.defineProperty() | Object.defineProperty() | Reflect 返回布尔值,Object 返回对象或抛出异常 |
Reflect.getOwnPropertyDescriptor() | Object.getOwnPropertyDescriptor() | 基本相同 |
Reflect.getPrototypeOf() | Object.getPrototypeOf() | Reflect 对非对象参数会抛出 TypeError |
Reflect.ownKeys() | Object.getOwnPropertyNames() + Object.getOwnPropertySymbols() | Reflect 返回所有键(包括 Symbol) |
总结
Reflect 提供了一套统一、函数式的 API 来操作对象,特别适合:
- 元编程:动态操作对象属性和行为
- 与 Proxy 配合:实现代理对象的默认行为
- 函数式编程:将操作符转换为函数调用
- 错误处理:通过返回值而不是异常来处理失败情况
Reflect 是现代 JavaScript 元编程的重要工具,在框架开发和高级应用中发挥着重要作用。