美文网首页
Proxy(代理)

Proxy(代理)

作者: 我家有个王胖胖 | 来源:发表于2022-03-09 21:54 被阅读0次

    ES5:Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
    详细讲解
    基本用法:

    Object.defineProperty(obj, prop, desc)
    

    参数说明:

    • obj 需要定义属性的当前对象
    • prop 当前需要定义的属性名
    • desc 属性描述符
      通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符。
      数据描述符:
      writeable:是否可以修改
     let person = {}
    Object.defineProperty(person,'name',{
        value:'张三',
        writeable:false//默认为false,默认可省略
    })
    person.name = '李四'
    console.log(person.name);//张三
    
    let person = {}
    Object.defineProperty(person,'name',{
        value:'张三',
        writeable:true//默认为false,默认可省略
    })
    person.name = '李四'
    console.log(person.name);//李四
    

    存取描述符:
    get:一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
    set:一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined。

    let person = {}
    let temp = null;//给他赋值,防止set方法陷入死循环
    Object.defineProperty(person,name,{
        get: function() {
            return temp;
        },
        set: function(val) { 
            temp = val;
        }
    })
    person.name = '张三';
    console.log(person.name);
    

    注意

    数据描述符和存取描述均具有以下描述符
    configrable 能否使用delete、能否需改属性特性、或能否修改访问器属性
    enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中

            let person = {};
            Object.defineProperty(person, 'name', {
                    value: '张三',
                    writable: true,
                    configurable: false
    
                })
                //person.name = '李四';
            Object.defineProperty(person, 'name', {
                value: '李四',
            })
            console.log(person.name); //Cannot redefine property: name
    
    let person = {
            name: "张三",
          };
          Object.defineProperty(person, "name", {
            configurable: false,
            enumerable: true,
            writable: false,
          });
          delete p.name;//"TypeError: Cannot delete property 'name' of #<Object>"
    

    configrable:true 通过属性定义的方式可以被修改

    let person = {};
            Object.defineProperty(person, 'name', {
                value: '张三',
                configrable: true,
                writable: true,
                enumerable: true
    
            })
            Object.defineProperty(person, 'name', {
                value: 'lisi',
            })
            console.log(person);//lisi
            delete person.name 
            console.log(person);//undefine
    

    <meta charset="utf-8">

    enumerable:


    enumerable.png 默认属性值.png

    对象常量
    结合writable: false 和 configurable: false 就可以创建一个真正的常量属性(不可修改,不可重新定义或者删除)


    对象常量.png

    禁止扩展:

    let person = {
            name: "张三",
          };
          Object.preventExtensions(person)
          person.gender = '女';//"TypeError: Cannot add property gender, object is not extensible"
          console.log(person);
    

    密封
    Object.seal()会创建一个密封的对象,这个方法实际上会在一个现有对象上调用object.preventExtensions(...)并把所有现有属性标记为configurable:false。

    密封.png

    所以, 密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以改属性的值)

    冻结: vue中纯数据的展示,可以冻结对象,取消绑定,提升性能
    Object.freeze()会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(),并把所有现有属性标记为writable: false,这样就无法修改它们的值。


    冻结.png

    ES6:Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写
    基本用法:

    let p = new Proxy(target, handler);
    

    参数说明:
    1.target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
    2.handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。具体的handler相关函数请查阅官网
    ①get:属性读取操作的捕捉器

    let person = {
        name:'张三',
        age:18
    }
    person = new Proxy(person,{
        get(target,key) {
            console.log('获取属性');
            if (key === 'age') {
                return target[key] +'岁'
            }
            return target[key];
        }
    })
    
    console.log(person.age);//18岁
    

    ②set:属性设置操作的捕捉器。

    let person = {
        name:'张三',
        age:18
    }
    person = new Proxy(person,{
        set(target,key,val) {
            console.log('设置属性');
            if(typeof target[key] === 'number'){
                target[key] =  val + '岁';
            }else{
                target[key] = val;
            }
        }
    })
    
    person.age = 19;
    console.log(person.age);
    

    ③has:操作符的捕捉器。检查是否存在属性。

    //has
    let range= {
        start:1,
        end:5
    }
    range = new Proxy(range,{
        has:function(target,key){
            return key >= target.start && key <= target.end;
        }
    })
    console.log(2 in range);//true
    console.log(9 in range);//false
    

    ④ownkeys:对对象的循环遍历进行拦截

    //保护_password不可被遍历
    let person = {
        name: '张三',
        age: 18,
        _password: '****'
    }
    person = new Proxy(person, {
        ownKeys(target) {
            return Object.keys(target).filter(item =>
                !item.startsWith('_')
            )
        }
    });
    console.log(Object.keys(person));//['name', 'age']
    

    ⑤deleteProperty:删除拦截器

    let person2 = {
        name: '李四',
        age: 19,
        _password: '****'
    }
    person2 = new Proxy(person2, {
        deleteProperty(target, prop) {
            if (prop.startsWith('_')) {
                throw new Error('不可删除')
            } else {
                delete target[prop];
                return true;
            }
        }
    })
    try {
        delete person2._password
    } catch (e) {
        console.log(e.message);//不可删除
    
    }
    

    ⑥apply拦截函数操作

    let sum = function (...args) {
        let sum = 0;
        args.forEach(item => {
            sum += item;
        })
        return sum;
    }
    sum = new Proxy(sum, {
        apply(target,context,args) {
            return target(...args)*2;
        }
    })
    
    console.log(sum(1,2,3));//12
    console.log(sum.call(null,1,2,3,4));//20
    console.log(sum.apply(null,[1,2,3,4]));//20
    

    ⑦construct 拦截new 命令

    function People(name){
        this.name = name;
    }
    console.log(People);
    let proxy = new Proxy(People,{
        construct:function(target, argumentsList, newTarget) {
            console.log('拦截到了');
            return new target(...argumentsList);
        }
    })
    console.log(new proxy('张三'));
    

    proxy拦截器总结:


    proxy拦截器总结1.png
    proxy拦截器总结2.png

    Reflect:

    Reflect简介.png
    reflect详细介绍

    Object.defineProperty与Proxy的区别

    相关文章

      网友评论

          本文标题:Proxy(代理)

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