关于es6代理对象proxy

代理 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。所以,这个属性还是需要谨慎使用诶。。

posted @ 2017-10-29 12:48  天下大雨  阅读(550)  评论(0编辑  收藏  举报