代理 Proxy
ES6规范定义了一个全新的全局构造函数:代理(Proxy)。
它可以接受两个参数:
target:用Proxy
包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handle: 一个对象,其属性是当执行一个操作时定义代理的行为的函数。
基础示例
let handler = { get: function(target, name){ return name in target ? target[name] : 37; } }; let p = new Proxy({}, handler); p.a = 1; p.b = undefined; console.log(p.a, p.b); // 1, undefined console.log('c' in p, p.c); // false, 37
在上面的例子中,我们对一个对象进行了代理,当对象中不存在属性名时,缺省返回数为37
。
无操作转发代理
let target = {}; let p = new Proxy(target, {}); p.a = 37; // 操作转发到目标 console.log(target.a); // 37. 操作已经被正确地转发
对象传值验证
let validator = { set: function(obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new TypeError('The age is not an integer'); } if (value > 200) { throw new RangeError('The age seems invalid'); } } // The default behavior to store the value obj[prop] = value; } }; let person = new Proxy({}, validator); person.age = 100; console.log(person.age); // 100 person.age = 'young'; // 抛出异常: Uncaught TypeError: The age is not an integer person.age = 300; // 抛出异常: Uncaught RangeError: The age seems invalid
最近在学习vue.js的源码,发现很多地方都用到了proxy代理来进行验证,比如说keycodes的设置
先看官网的说明
看源码中对keycodes的验证
//vue/src/core/instance/proxy.js /** *.... */ const hasProxy = typeof Proxy !== 'undefined' && Proxy.toString().match(/native code/) if (hasProxy) { const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact') config.keyCodes = new Proxy(config.keyCodes, { set (target, key, value) { if (isBuiltInModifier(key)) { warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`) return false } else { target[key] = value return true } } }) } /** *.... */
对config的keyCodes对象进行了代理,当设置其属性时就会进行验证,如果是这是stop,prevent,self,ctrl,shift,alt,meta,exact这些属性,就会报错
当我这样设置的时候
Vue.config.keyCodes.ctrl = 13;
就会得到这样的结果
proxy对象其实就相当于一个对象拦截器,可以观察或记录对象访问。其应用场景当然肯定不仅仅用于验证,这里暂时就不深入学习了。不过话说回来,proxy对象作为es6的标准,其兼容性不是很好,目前只有Firefox,chrome和微软的Edge支持代理,而且还没有支持这一特性polyfill。所以,这个属性还是需要谨慎使用诶。。