美文网首页
ECMAScript6--13.Proxy和Reflect

ECMAScript6--13.Proxy和Reflect

作者: 飞菲fly | 来源:发表于2017-10-21 16:09 被阅读20次

1.Proxy和Reflect

  • Proxy:代理;连接了用户和最真实对象中间一个层;

  • Reflect :反射;反射的Object;

    • Proxy对象和Reflect对象的方法是一模一样的;
      • var obj = new Proxy(要代理的对象,{实现要代理的东西(方法)});
      • var obj2 = Reflect();
  • Proxy和Reflect的概念

  • Proxy和Reflect的适用场景

2.

 {
//供应商,原始对象来存储真实的数据;
//1.有一个类似于供应商的原生数据对象obj;
let obj = {
    time:'2017-10-15',
    name:'net',
    _r:123
};

//创建一个代理商;
//2.通过Proxy新生成一个对象,这个对象是映射Obj的;然后再中间做一些操作;
let monitor = new Proxy(obj,{
    //代理了所有对象属性的读取的一个作用;
    //(拦截对象属性的读取,拦截和代理是一个意思;)
    //拦截代理所有跟读取相关的属性;
    get(target,key){
        //不管读取什么属性,要把所有属性中值的2017替换成2018
        return target[key].replace('2017','2018');
    },
    //拦截对象设置属性
    //不让修改除了name属性以外的属性;
    set(target,key,value){
        if(key ==='name'){
            //把新设置的value赋值给这个对象target也就是obj;
            return target[key] = value;
        }else{
            return target[key];
        }
    },
    //判断当前对象中是不是拥有某个属性;in运算符判断在一个对象中;
    //拦截key in object 操作;
    has(target,key){
        //只暴露name属性,其他的都不暴露;
        if(key ==='name'){
            return target[key];
        }else{
            return false;
        }
    },
    //删除,object有个属性通过delete运算符就可以删除那个属性;
    //通过代理Proxy拦截这种操作;实现了对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){
      //通过Object.keys把原始对象所有的keys都拿出来,在基础上进行过滤;如果是time就不返回;
        //过滤掉time这个属性,达到了保护time属性的真实做法;
        return Object.keys(target).filter(item=>item!='time');
    }
});


//3.用户访问的是monitor,不管用户是读取monitor对象、还是设置monitor对象的属性,
//最终通过Proxy在传给这个obj对象;
//从monitor中读取点(.)后面的属性time;
 console.log('get',monitor.time); //get 2018-10-15
 
 monitor.time = '2018';
 monitor.name ='abc';
 console.log('set',monitor.time,monitor); 
 //set 2018-10-15 Proxy{time:"2017-10-15",name:"abc",_r:123}

//通过代理欺骗了用户,这就是代理所起的作用;
console.log('has','name' in monitor, 'time' in monitor); //has true false


//delete monitor.time;
//console.log('delete',monitor);
//delete Proxy{time:"2017-10-15",name:"abc",_r:123}


//delete monitor._r;
//console.log('deleter_r',monitor);
//deleter_r Proxy{time:"2017-10-15",name:"abc"}

console.log('ownKeys',Object.keys(monitor)); 
 //ownKeys ["name","_r"] 只返回了name、_r,time被保护起来了;

 }

3.Reflect (Proxy对象有的方法Reflect都有,名称和用法一摸一样)

要改变直接操作Object的行为习惯,通过Reflect来取和操作;

{
    let obj = {
        time:'2017-10-15',
        name:'net',
        _r:123
    };
    
    //用reflect读取这个对象
    consoel.log('Reflect get',Reflect.get(obj,'time'));
    //Reflect get 2017-10-15
    
    Reflect.set(obj,'name','abc');
    console.log(obj);
    //Object {time:"2017-10-15",name:"abc",_r:123}
    
    //判断obj是不是有name这个属性;
    console.log('has',Reflect.has(obj,'name');
    //has true
    
}

4. 真正的开发中怎么去用这个特性呢?

  • 传统做法:如果对某个属性进行限制,在赋值的时候对它进行判断,判断这个类型是不是合适,是不是满足其他条件,然后才允许修改这个对象;
  • 通过代理的方式把条件和这个对象(业务逻辑)本身完全隔离开,在后期代码维护中,这个时候要加一个手机号的验证扩展,在这个对象类中增加一个mobile,在personValidators中对应加一个mobile限制;后期代码维护,代码整洁度,健壮性,复用性是非常强的;
{
 //开发中对一些数据进行校验:
 //比如:年龄不是是满足什么样的条件;手机号--点提交的时候判断数据类型是不是这样的;
 //通过用Proxy和Reflect实现一个和业务解耦的校验模块;
 //提供代理;
 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 Errow(`不能设置${key}到${value}`);
                }
            }else{
                throw Errow(`${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 = '1111';
        
        //构造函数返回了Proxy对象,这个proxy对象拦截了(代理了)Person对象;
        //在外边操作,并不是真正的操作Person这个类的实例;而是通过Proxy对象对target
        的一个代理,这个target是this,this就是Person的实例,Person类实例以后其实得到
        的是一个对Person实例对象代理的proxy对象;
        return validator(this,personValidatorss);
    }
 }
 
 const person = new Person('lilei',30);
 console.info(person);
 //Proxy{name:"lilei",age:30}
    
 //person.name = 48; //报错不能设置name到48
 
 person.name = 'hanmeimei'; 
 console.info(person); //Proxy{name:"hanmeimei",age:30}
}

相关文章

  • ECMAScript6--13.Proxy和Reflect

    1.Proxy和Reflect Proxy:代理;连接了用户和最真实对象中间一个层; Reflect :反射;反射...

  • (二)16.Proxy和Reflect19-08-13

    Proxy和ReflectProxy和Reflect的概念Proxy :代理Reflect:反射 Proxy 打印...

  • 反射

    什么是反射? 为何需要检查变量,确定变量的类型? reflect 包reflect.Type 和 reflect....

  • 反射的用法

    什么是反射? 为何需要检查变量,确定变量的类型? reflect 包reflect.Type 和 reflect....

  • Proxy和Reflect

    Proxy代理## get set delete 结果 ownKeys Reflect## Reflect和Rro...

  • ES6(十二)—— Reflect

    Reflect 反射,什么是反射机制? Reflect简介 为什么要用Reflect? Reflect API.a...

  • Reflect反射与代理Proxy

    先看看Reflect有多少属性方法 所以Reflect.set()与Reflect.get()相反 Reflect...

  • golang-reflect

    reflect 示例0 reflect示例1 reflect 示例2 通过反射修改对象属性 reflect 示例3...

  • Proxy和Reflect

    Proxy 概述 Proxy在目标对象之前架设一层"拦截",外界对该对象访问必须先通过这层拦截.因此提供了一种极致...

  • Proxy和Reflect

    Proxy和Reflect 拦截操作get(target,propKey,receiver) 读取属性时拦截拦截器...

网友评论

      本文标题:ECMAScript6--13.Proxy和Reflect

      本文链接:https://www.haomeiwen.com/subject/egiiuxtx.html