一. 概述
- Reflect对象和Proxy对象都是ES6为了操作对象而提供的新API,Reflect对象的设计目的有:
- 将object对象的一些明显属于语言内部的方法放到Reflect对象上。也就是从Reflect对象上可以拿到语言内部的方法
- 可以修改某些Object对象方法的返回结果,使其变得更加合理。
- 可以让Object对象的操作都变成函数行为。例如:
name in obj和delete obj.age可以改为使用Reflect.has(obj,name),Reflect.deleteProperty(obj,age) - Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法,
也就是不管Proxy怎么修改默认行为,总是可以在Reflect上获取到默认行为
二. Reflect的静态方法
1. Reflect.get
- 查找并返回target对象的xxx属性,如果没有该属性,则返回undefined;
- 参数有三个,target表示目标对象
如果参数不是Object则报错,name表示对象的属性,receiver表示内部的this - 例子:
var obj={
foo:1,
func:2,
get sum(){
return this.foo+this.func;
}
}
console.log(Reflect.get(obj,'foo'));
console.log(Reflect.get(obj,'func'));
console.log(Reflect.get(obj,'sum'));
var other={foo:22,func:90}
console.log(Reflect.get(obj,'sum',other));
console.log(Reflect.get(obj,'foo',other));
console.log(Reflect.get(obj,'func',other));
2. Reflect.set
- Reflect.set方法设置target对象的name属性等于value
- 有四个参数:target表示目标对象,name表示对象属性名称,value表示属性值,receiver表示绑定target对象内部方法的this为receiver对象!
var obj={
foo:3,
set bar(val){
console.log(this.foo+val)
return ;
}
}
var other={foo:9999}
console.log(Reflect.set(obj,'bar',1));
console.log(Reflect.set(obj,'bar',1,other));
3. Reflect.has
- Reflect.has方法对应name in obj里面的
in运算符,如果第一个参数不是对象,会报错
var obj={name:'ww'}
console.log('name' in obj);
console.log('age' in obj)
console.log(Reflect.has(obj,'name'))
console.log(Reflect.has(obj,'age'))
4. Reflect.apply
- Reflect.apply方法等同于
Function.prototype.apply.call(func,thisArg,args),用于绑定this对象给func函数,参数为func,thisArg,args;thisArg表示绑定的this对象;Reflect.apply(func,thisArgs,args)相当于func.apply(thisArg,args) 如果要绑定一个函数的this对象,可以写成func.apply(obj,args),但是如果函数定义了自己的apply方法,那么就只能写成Function.prototype.apply.call(fn,obj,args),采用Reflect对象可以简化这种操作
var args=[1,3,5,11,9,76]
console.log(Math.min.apply(Math,args));
console.log(Math.max.apply(Math,args));
console.log(Reflect.apply(Math.min,Math,args))
console.log(Reflect.apply(Math.max,Math,args))
5. Reflect.defineProperty
- Reflect.defineProperty方法等同于Object.defineProperty,用于为对象定义属性
经常和Proxy.defineProperty结合
var p=new Proxy({},{
defineProperty(target,name,val){
return Reflect.defineProperty(target,name,val)
}
})
p.foo="bar"
console.log(p.foo);
三. 实现观察者模式
观察者模式就是函数自动观察数据对象,一旦对象有变化,函数就会自动执行- 思路;通过observable函数创建一个代理器对象,该observable函数内部监听set操作方法;
- 在代理器对象person的属性值改变之后,就会触发监听器函数handle;
- 而handle会遍历执行通过observe函数放入执行栈中的待执行函数,从而在对象的属性值改变同时可以执行多个其他函数.
var set=new Set();// 集合
var observe=function(fn){
return set.add(fn)
};// 添加值到集合中
var observable=function(obj){
return new Proxy(obj,{set:handle});
}
function handle(target,name,val,receiver){
var res=Reflect.set(target,name,val,receiver);
set.forEach(item => item(name,val));// 执行函数
return res;
}
// 返回代理器对象
const person = observable({
name: '张三',
age: 20
});
function print() {
console.log(`${person.name}, ${person.age}`)
}
observe(print);
console.log(set);//Set(1) {ƒ} 指的是print函数
person.name = '李四';
function other(name,val){
console.log(`other:${name}改为${val}`)
}
observe(other);
person.age=99;