proxy 和 Object.defineProject 的区别
- Object.defineProject 只有一次劫持一个对象中的属性,所以一般劫持对象是需要遍历劫持的,而proxy 直接劫持整个对象
- Object.defineProject 监听不到数组长度的变化,需要进行一些 hack , 而 Proxy 不需要那么多hack,就可以无压力监听数组的变化,我们都知道,标准永远优先于hack。
- Proxy 最大的劣势就是他的兼容性问题,
proxy 是用来干什么的
proxy 就是一个代理,用来帮我们做对数据的处理,构造函数的处理,对数据的验证,说白了,就是在外面访问对象前添加了一层拦截,可以过滤很多操作,而这些过滤由你定义;
let p = new Proxy(target, handler);
/**
* target:需要使用Proxy包装的目标对象
*(可以使任何类型的对象,包括原生数组,函数,甚至另一个代理)
* handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数
*/
let test = {
name: "小红"
};
test = new Proxy(test, {
get(target, key) {
console.log('获取了getter属性');
return target[key];
}
// target是这个对象,key是键名,value是要修改的新值
set(target, key, value) {
if (key === "age" && typeof value !== "number") {
throw Error("age字段必须为Number类型");
}
return Reflect.set(target, key, value);
}
});
console.log(test.name);
// 结果是 先打印 ‘获取了getter属性’这句话,然后打印小红。
代理就是实现响应式数据的关键,因为一但数据被代理,那么拿数据的时候就会执行get方法,修改数据的时候就会执行set方法,如果你在set或者get里面添加一些操作,那么一但这个方法被触发,你添加的操作也会被触发
Proxy 一般和Reflect配套使用
Reflect 是什么 ?
- 首先这个概念是ES6提出来的,为了操作对象而提供的API ,以下的熟知
Reflect对象是一个全局的普通的对象。Reflect的原型就是Object.
- 将Object对象的一些明显属于语言内部的方法(比如Obejcet.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object喝Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从reflect对象上可以拿到语言内部的方法。
- 在使用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上获取默认行为。