Proxy
- Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程
- Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
```javascript
{
// ES5
let obj = {};
let newVal = “”;
Object.defineProperty(obj, “name”, {
get() {
}, set(val) {return newVal;
}, }); obj.name = “wuchendi”; console.log(obj.name); // wuchendi }newVal = val;
{ let obj = { time: “2017-03-11”, name: “wcd”, r: 123, }; let monitor = new Proxy(obj, { // 拦截对象属性的读取 get(target, key) { return target[key].replace(“2017”, “2018”); }, // 拦截对象设置属性 set(target, key, value) { if (key === “name”) { return (target[key] = value); } else { return target[key]; } }, // 拦截key in object操作 has(target, key) { if (key === “name”) { return target[key]; } else { return false; } }, // 拦截delete deleteProperty(target, key) { if (key.indexOf(““) > -1) { delete target[key]; return true; } else { return target[key]; } }, // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames ownKeys(target) { return Object.keys(target).filter((item) => item != “time”); }, });
console.log("get", monitor.time); // get 2018-03-11monitor.time = "2018";monitor.name = "wuchendi";console.log("set", monitor.time, monitor); // set 2018-03-11 Proxy {time: "2017-03-11", name: "wuchendi", _r: 123}console.log("has", "name" in monitor, "time" in monitor); // has true false// delete monitor.time;// console.log('delete', monitor);// delete monitor._r;// console.log('delete', monitor);console.log("ownKeys", Object.keys(monitor)); // ownKeys ["name", "_r"]
}
{ // apply let sum = (…args) => { let num = 0; args.forEach((item) => { num += item; }); return num; };
sum = new Proxy(sum, {apply(target, ctx, args) {return target(...args) * 2;},});console.log(sum(1, 2)); // 6console.log(sum.call(null, 1, 2, 3)); // 12console.log(sum.apply(null, [1, 2, 3])); // 12
}
{ //constructor new let User = class { constructor(name) { this.name = name; } };
User = new Proxy(User, {construct(target, args, newTarget) {return new target(...args);},
}); console.log(new User(“wuchendi”)); // User { name: ‘wuchendi’ } }
<a name="xsYgP"></a>## Reflect- Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。 Reflect 对象的设计目的有这样几个。- 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty),放到 Reflect 对象上。现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来的新方法将只部署在 Reflect 对象上- 修改某些 Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc)则会返回 false- 让Object 操作变成函数行为- Reflect 对象的方法与 Proxy 对象的方法一一对应```javascript{let obj = {time: "2017-03-11",name: "wcd",_r: 123,};console.log("Reflect get", Reflect.get(obj, "time")); // Reflect get 2017-03-11Reflect.set(obj, "name", "wuchendi");console.log(obj); // { time: '2017-03-11', name: 'wuchendi', _r: 123 }console.log("has", Reflect.has(obj, "name")); // has true}{function validator(target, validator) {return new Proxy(target, {_validator: validator,set(target, key, value, proxy) {if (target.hasOwnProperty(key)) {let va = this._validator[key];if (!!va(value)) {return Reflect.set(target, key, value, proxy);} else {throw Error(`不能设置${key}到${value}`);}} else {throw Error(`${key} 不存在`);}},});}const personValidators = {name(val) {return typeof val === "string";},age(val) {return typeof val === "number" && val > 18;},mobile(val) {},};class Person {constructor(name, age) {this.name = name;this.age = age;this.mobile = "189****0530";return validator(this, personValidators);}}const person = new Person("wuchendi", 22);console.info(person); // Person { name: 'wuchendi', age: 22, mobile: '189****0530' }person.name = "dd";console.info(person); // Person { name: 'dd', age: 22, mobile: '189****0530' }}
