ES6中的代理Proxy和反射Reflect

 一、代理Proxy

1.Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程

2.Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

3.Proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作(后文会说明,有哪些操作可以拦截),必须通过这层拦截。

let p = new Proxy(target,handler)

  • 用Proxy包装的目标对象

  • 是个配置,一个对象,对代理对象进行拦截操作的函数,如set、get...

3.常用方法

  • get读取
{
    let account = {
        id: 999,
        name: 'admin',
        phone: '12345678910',
        creat_time: '2021-10-05',
        _private: 'demo'//假设是私有的,过滤的时候对他进行保护
    }
    let accountProxy = new Proxy(account, {
        //读取的时候进行拦截
        //手机号中间四位变****,修改创建时间
        //此处的target指的是account
        get: function (target, key){
            switch (key) {
                case 'phone':
                    return target[key].substring(0, 3) + '****' +target[key].substring(7)
                    break;
                case 'creat_time':
                    return target[key].replace('2021-10-05', '1991-10-05')
                    break;
                default:
                    return target[key];
                    break;
            }
        })
    console.log('拦截读取', accountProxy.phone, accountProxy.creat_time);
}
  • set设置
{
    let obj = {
        id: '111',
        name: 'aaa',
        phone: '12345678910',
        creat_time: '2001-10-22',
        _private: 'demo'
    }
    let objProxy = new Proxy(obj, {
        //拦截设置
        //id不可更改  
        set:function(target,key,value){
            if(key==='id'){
                return target[key]//id不可更改,返回的是原始id对应的值
            }
            else{
                return target[key]=value
            }
        }
    })
    objProxy.id='6666'
    objProxy.name='bbb'
    console.log('拦截设置',objProxy.name,objProxy.id);//bbb 111
}
  • has判断key是否存在
{
    let obj = {
        id: '111',
        name: 'aaa',
        phone: '12345678910',
        creat_time: '2001-10-22',
        _private: 'demo'
    }
    let objProxy = new Proxy(obj, {
        //判断key是否存在
        has: function (target, key) {
            if (key in target) {
                console.log(`${key}:${target[key]}`);
                return true;
            }
            else {
                console.log('没有这个属性');
                return false;
            }
        }
    })

    console.log('拦截has', 'gender' in objProxy);//没有这个属性 has false
}
  • deleteProperty拦截delete
{
    let obj = {
        id: '111',
        name: 'aaa',
        phone: '12345678910',
        creat_time: '2001-10-22',
        _private: 'demo'
    }
    let objProxy = new Proxy(obj, {
        deleteProperty: function (target, key) {
            //拦截delete
            //以_开头的某个属性,不可删除,其余的全部都可以删
            if (key.indexOf('_') === 0) {
                console.warn('私有属性不可删除');
                return true//代表的是deleteProperty方法执行的成功还是失败,如果返回false,代表执行方法失败
            }
            else {
                delete target[key]
                console.log('删除成功');
                return true
            }
        }
    })
    console.log('拦截delete', delete objProxy._private);//私有属性不可删除 拦截delete true
    console.log('拦截delete', delete objProxy.name);//删除成功 拦截delete true
}
  • ownKeys拦截Object.keys等
{
    let obj = {
        id: '111',
        name: 'aaa',
        phone: '12345678910',
        creat_time: '2001-10-22',
        _private: 'demo'
    }
    let objProxy = new Proxy(obj, {
        //拦截Object.key()
        //如果属性是id或者是私有属性就不输出
        ownKeys(target){
            return Object.keys(target).filter(item=>{
                return item.indexOf('_')!=0 && item !='id'
            })
        }
    })
    console.log('拦截Object.keys()方法', Object.keys(objProxy));//['name', 'phone', 'creat_time']
}

二、反射Reflect

  • Reflect对象与Proxy对象一样是ES6为了操作对象引入的新API,它将对象里一些明显属于语言内部的方法移植到Reflect对象上,它对某些方法的返回结果进行了修改,使其更合理,并且使用函数的方式实现了Object的命令式操作。
  • Reflect并非一个构造函数,所以不能通过new运算符对其进行调用,或者将Reflect对象作为一个函数来调用。
{    
    //错误
    Reflect()// Reflect is not a function
}
  • Reflect对象是一个全局的普通的对象,它所有属性和方法都是静态的。

Reflect.get(target, name, receiver)

Reflect.set(target, name, value, receiver)

Reflect.apply(target, thisArg, args)

Reflect.construct(target, args)

Reflect.defineProperty(target, name, desc)

Reflect.deleteProperty(target, name)

Reflect.has(target, name)

Reflect.ownKeys(target)

Reflect.isExtensible(target)

Reflect.preventExtensions(target)

Reflect.getOwnPropertyDescriptor(target, name)

Reflect.getPrototypeOf(target)

Reflect.setPrototypeOf(target, prototype)

{
    let obj = {
        name: '拉拉',
        age: 11,
        gender: 'man',
        hobbies: 'sing'
    }
    //get
    console.log('Reflect', Reflect.get(obj, 'name'));//Reflect 拉拉
    //set
    Reflect.set(obj, 'name', '喜喜')
    console.log('Reflect', obj.name);//Reflect 喜喜
    //has
    console.log('Reflect', Reflect.has(obj, 'name'));//Reflect true
    console.log('Reflect', Reflect.has(obj, 'a'));//Reflect false
}
  • 当target对象中存在get方法,如果有receiver则this指向receiver 
{
 let exam = {
        name: 'aaa',
        age: 12,
        get info() {
            return this.name + this.age
        }
    }
    console.log(Reflect.get(exam, 'info'));//aaa12
    console.log(Reflect.get(exam, 'name'));//aaa
    // 当target对象中存在get方法,如果有receiver则this指向receiver
    let receiver = {
        name: 'bbb',
        age: 29
    }
    console.log(Reflect.get(exam, 'info', receiver));//bbb29
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值