ES6 中的Reflect和Proxy
Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。
Reflect 反射
Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式,函数式编程。它的方法与 Proxy 是对应的。
const obj ={
a:1,
b:2
}
// Reflect api方法
1.Refect.set(target,propertyKey,value) 给对象赋值
Reflect.set(obj,"a",10);
console.log(obj);//{a: 10, b: 2}
2.Reflect.get(target,propertyKey)取值
console.log(Reflect.get(obj,"a"));//10
//没有该属性,则返回undefined。
3.Reflect.apply(target,this.argumebnts)调用函数
function fun(a,b){
return a+b
}
console.log(Reflect.apply(fun,null,[2,5]));//7
4.Reflect.defineProperty(target,propertyKey);用于为目标对象定义属性
Reflect.defineProperty(obj,"a",{
})
//Reflect.defineProperty方法的作用与Object.defineProperty一样,都是为对象定义一个属性
//不同如下
// 失败时抛出错误
Object.defineProperty(obj, name, desc);
// 失败时返回false
Reflect.defineProperty(obj, name, desc);
5.Reflect.deleteProperty(target,propertyKey)用于删除 obj 对象的 propertyKey属性
//等同于 delete obj.a
Reflect.deleteProperty(obj,"a");
console.log(obj); //{b: 2}
6.Reflect.construct(target,arguments) 不使用new,来调用构造函数的方法。
function Test(a,b){
this.a =a;
this.b=b;
}
const t = Reflect.construct(Test,[2,3])
console.log(t);//Test {a: 2, b: 3}
//等同于new target(...args),
7.Reflect.has(target,propertyKey)查找属性在对象中是否存在
console.log(Reflect.has(obj,'c')); // false
//等同于
console.log('c' in obj); //false
Proxy 代理
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
//提供了修改底层实现的方式
let proxy = new Proxy(target, handler);
// target:目标对象
// handle: 一个普通对象,可以去重写第层方法
//会返回一个对象
let obj = {
a : 1,
b : 2
}
let proxy = new Proxy(obj,{
set(target,propertyKey,value){
Reflect.set(target,propertyKey,value)
},
get(target,propertyKey){
return Reflect.get(target,propertyKey)
},
delete(target,property){
Reflect.deleteProperty(target,propertyKey)
},
has(target,propertyKey){
Reflect.has(target,propertyKey)
}
})
proxy.a = 10;
console.log(proxy);//Proxy {a: 10, b: 2}
this 问题
在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理
const target = {
m: function () {
console.log(this === proxy);
}
};
const handler = {};
const proxy = new Proxy(target, handler);
target.m() // false
proxy.m() // true
//一旦proxy代理target.m,后者内部的this就是指向proxy,而不是target。
由于this指向的变化,会导致 Proxy 无法代理目标对象
有些原生对象的内部属性,只有通过正确的this才能拿到,所以 Proxy 也无法代理这些原生对象的属性