(1)将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty
),放到Reflect对象上。
(2)修改某些Object方法的返回结果。例如Object.defineProperty(obj, name, desc)
在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)
则会返回false。
(3)让Object操作都变成函数行为。例如原来的key in obj
和delete obj[key]
,Reflect.hasProperty(obj,key)
和Reflect.deleteProperty(obj,key)
让其变为函数
(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target,name, value, receiver);
if (success) {
log('property ' + name + ' on ' + target + ' set to ' + value);
}
return success;
}
});
上述代码拦截了对象的属性设置操作,但其在内部又调用了默认的属性复制行为
Reflect对象的大部分方法与Object对象的同名方法作用是相同的,且与Proxy对象方法对应
Reflect.apply(target, thisArg, args)
:该方法等同于function.prototype.apply.call(func, thisArg, args)function.prototype.apply.call(func, thisArg, args);
// 等同于
(FuncApply).call(func,thisArg,args);
// 等同于
func.FuncApply(thisArg,args);
// 等同于
func.apply(thisArg,args);
// 等同于
thisArgs.func(args);
// 为什么不直接写成func.apply(thisArg,args)呢,这是因为有可能函数本身定义了自己apply方法
Reflect.construct(target, args)
:该方法等同于new target(…args)Reflect.get(target, name, receiver)
:查找并返回target对象的name属性,函数中this绑定receiver参数//this 绑定receiver参数
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
};
var myReceiverObject = {
foo: 4,
bar: 4,
};
Reflect.get(myObject, 'baz', myReceiverObject) // 8
Reflect.set(target, name, value, receiver)
:设置target对象的name属性值为value,函数中this绑定receiver参数,该方法的调用会触发Proxy.defineProperty拦截Reflect.defineProperty(target, name, desc)
:等同于Object.defineProperty,如果第一个参数不是对象,会报错Reflect.deleteProperty(target, name)
:等同于delete obj[name],用于删除对象属性,成功返回trueReflect.has(target, name)
:对应于key in obj的in运算符,如果第一个参数不是对象,会报错Reflect.ownKeys(target)
:返回对象自身所有属性,等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和Reflect.isExtensible(target)
:对应于Object.isExtensible(target),如果第一个参数不是对象,会报错Reflect.preventExtensions(target)
:对应于Object.preventExtensions(target),使对象不可扩展,如果参数不是对象,会报错Reflect.getOwnPropertyDescriptor(target, name)
:等同于Object.getOwnPropertyDescriptor,如果第一个参数不是对象,会报错Reflect.getPrototypeOf(target)
:读取对象的原型对象。其与Object.getPrototypeOf(target)区别在于,如果参数不是对象,后者会先转换为对象,而前者报错Reflect.setPrototypeOf(target, prototype)
:设置对象的原型对象。如果第一个参数不是对象或为null、undefined,直接报错实例使用Proxy实现观察者模式
const person = observable({
name: '张三',
age: 20
});
function print() {
console.log(`${person.name}, ${person.age}`)
}
observe(print);
person.name = '李四';
// 输出
// 李四, 20
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;
}
上述代码将所有观察者函数都放入集合中,然后拦截对象的属性赋值操作,一旦有属性改动,自动执行所有观察者函数