ES6新特性使用小结(四)

十一、Proxy 、Reflect

   ①、Proxy 的概念和常用方法

{     
    let obj = {                  //1、定义原始数据对象           对用户不可见
        time: '2017-09-20',
        name: 'net',
        _r: 123
    };

    let monitor = new Proxy(obj, {       //2、通过Proxy新生成一个对象  映射obj   代理所有对obj的操作
                                         //拦截对象的属性读取
        get(target, key){            //设置访问规则
            return target[key].replace('2017', '2018');
        },
        set(target, key, value){      //设置修改规则
            if (key === name) {
                return target[key] = value;       //只允许修改name
            } else {
                return target[key];
            }
        },

        //拦截 key in object 操作
        has(target, key){
            if (key === 'name') {
                return target[key];        //只暴露name属性
            } else {
                return false
            }
        },

        //拦截对 delete 操作
        deleteProperty(target, key){
            if (key.startsWith('_')) {        //只允许删除以 '_'开头的属性
                delete target[key];
            } else {
                return target[key];
            }
        },

        //拦截Object.keys(),Object.getOwnPropertySymbols(),Object,getOwnPropertyNames()   等方法
        ownKeys(target){
            return Object.keys(target).filter(item=>item != 'time');     //过滤掉  time 属性
        }
    });
    //3、用户访问的是 monitor
    console.log('get', monitor.time);                  //get   2018-09-20      读取的数据被代理修改了
    monitor.time = '2018-01-15';
    monitor.name = 'com';
    console.log('set', monitor.time, monitor.name);      //set 2018-09-20 net      time属性的修改无法生效

    console.log('has', 'name' in monitor, 'time' in monitor);    //has true false        time属性被我们拦截了

    delete monitor.time;
    delete monitor._r;
    console.log('delete', monitor);     //delete    Proxy {time: "2017-09-20", name: "net"}     _r属性被删除 而对time的操作被拦截

    console.log('ownKeys', Object.keys(monitor)) //ownKeys   ["name"]    time属性被拦截
}

  ②、Reflect 的概念和用法

{              **同Proxy
    let obj = {
        time: '2017-09-20',
        name: 'net',
        _r: 123
    };
    //              Reflect.get/set/has/ownKeys...(target,key,value);
    console.log('Reflect get', Reflect.get(obj, 'time'));         //Reflect get 2017-09-20

    console.log('Reflect set', Reflect.set(obj, 'name', 'com'), obj);
    //Reflect set true {time: "2017-09-20", name: "com", _r: 123}

    console.log('Reflect has', Reflect.has(obj, '_r'));           //Reflect has true

  ③、使用 Proxy 和 Reflect 实现业务的解耦

function validator(target, validator) {
    return new Proxy(target, {       //返回一个对target的代理
        _validator: validator,       //接收 验证规则
        set(target, key, value, proxy){             //定义 对 target的 修改规则
            if (target.hasOwnProperty(key)) {     //判断 target 的 key 是否存在
                let vali = this._validator[key];        //去除对应key 的验证规则
                if (!!vali(value)) {
                    return Reflect.set(target, key, value, proxy);
                } else {
                    throw Error(`无法设置${value}到${key}`);
                }
            } else {
                throw Error(`${key}不存在`)
            }
        }
    });
}
const userValidator = {       //定义验证规则
    name(val){
        return /[a-zA-Z0-9_]{3,12}/.test(val);
    },
    phone(val){
        return  /^1[3|4|5|8][0-9]d{4,8}$/.test(val)
    }
}

class User{
    constructor(name,phone){
        this.name=name;
        this.phone= phone;
        return validator(this,userValidator);       //得到一个 user的代理对象
    }
}
let u = new User();         //初始化 得到 user 的代理
//u.name = 'a'                //不符合 验证规则 抛出错误     无法设置a到name
console.log(u.name='Lain',u.phone=13797154666,u);       //Proxy {name: "Lain", phone: 13797154666}
原文地址:https://www.cnblogs.com/sunyaaa/p/ES6.html