ES6中Proxy与Reflect的简单学习笔记,他们也是vue3.0版本中数据劫持的重要API。
1、Proxy
Proxy也就是代理,在目标对象之前做一层拦截处理,可以对目标对象做很多操作。
语法:
let p = new
Proxy(target, handler);
参数:
target:需要被代理的目标对象,可以是任何数据类型的对象,即使是另一个代理对象;
handler:是一个对象,对象中设置对目标对象的拦截操作,包括set get等,具体查看Mdn,对于每一个被代理的操作都对应一个处理函数,该函数对数据做拦截操作;如果handler没有设置任何拦截,等同直接指向原对象,按照原先的生产方式输出;
简单列举get set在Proxy中的表现: 举个栗子(get):
let proxy = new
Proxy({}, {
get: function(target, property) {
return
"被拦截了";
}
});
proxy.time // 被拦截了
proxy.name // 被拦截了
proxy.title // 被拦截了
在上边的例子中,对一个空对象做了代理,并且重写了get方法做拦截,在后续的获取属性操作中,由于拦截的原因,无论访问什么属性都将得到“被拦截了”。其中get的第一个参数是目标对象第二个参数是要访问的属性。
再举个栗子(set):
let obj = {name : "zs",age:18}
let p = new
Proxy(obj,{
set(target,key,value){
console.log(target,key,value)
target[key] = "拦截"
}
})
p.name = "ls"
console.log(p)
结果为:
{ name: 'zs', age: 18 } 'name'
'ls'
{ name: '拦截', age: 18 }
set中的参数分别为目标对象 要设置的键 要设置成的值
但是由于重写set中的操作是将目标对象的键所对应的值设置为“拦截”,所以无论设置成什么值,最后再输出p,p的name值都为“拦截”。
在handlller中还有很多属性可以拦截,set与get是两个比价好理解的。 2、Rlfect Reflect也是跟Proxy都是在ES6中新增加的API,可以理解为对Object的美化。
(1)、将Object对象上一些明显属于语言内部的方法(如Object.defineProperty),放到Reflect上,现在阶段某些方法同时出现在Object与Reflect上,未来的新方法只会出现在Reflect上。
(2)、改善Object上某些方法的返回值,如Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc) 则会返回 false ;
// Object写法
try {
Object.defineProperty(target, property, attributes);
// todo...
} catch (e) {
// 处理异常
}
// Reflect写法
if (Reflect.defineProperty(target, property, attributes)) {
// todo....
} else {
// 返回flase时的处理逻辑
}
(3)、Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。
let p = new
Proxy(obj, {
get(target, name) {
console.log('get', target, name);
return
Reflect.get(target, name);
},
deleteProperty(target, name) {
console.log('delete' + name);
return
Reflect.deleteProperty(target, name);
},
has(target, name) {
console.log('has' + name);
return
Reflect.has(target, name);
}
});
所以在set的例子中完全可以使用Reflect.set()去完成赋值,使代码更健壮,
let obj = {name : "zs",age:18}
let p = new
Proxy(obj,{
set(target,key,value){
console.log(target,key,value)
// target[key] = "拦截"
return
Reflect.set(target,key,value)
}
})
p.name = "ls"
console.log(p)
这样就可以完成正常的赋值代理了;
Proxy与Reflect基本上都是成对使用的,方法是一一对相应的,优化了操作的返回值,对于简单的操作就分享到这。