Reflect
与大多数全局对象不同 Reflect 并非一个构造函数,所以不能通过 new 运算符对其进行调用。
静态方法
Reflect对象一共有 13 个静态方法。
Reflect.apply
(target, thisArg, args)Reflect.construct
(target, args)Reflect.get
(target, name, receiver)Reflect.set
(target, name, value, receiver)Reflect.defineProperty
(target, name, desc)Reflect.deleteProperty
(target, name)Reflect.has
(target, name)Reflect.ownKeys
(target)Reflect.isExtensible
(target)Reflect.preventExtensions
(target)Reflect.getOwnPropertyDescriptor
(target, name)Reflect.getPrototypeOf
(target)Reflect.setPrototypeOf
(target, prototype)
Reflect对象的设计目的有这样几个
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。
将Object对象的一些明显属于语言内部的方法放到 Reflect 对象上(比如Object.defineProperty)。
修改某些Object方法的返回结果,让其变得更合理。
比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误
而Reflect.defineProperty(obj, name, desc)则会返回false。让 Object 操作都变成函数行为。
某些Object操作是命令式,比如name in obj和delete obj[name]
而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
使用 Proxy 实现一个简单 观察者模式
javascript
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}