ES6-11 总结六 (代理Proxy 反射Reflect)

1 Proxy 代理

1.1 Es5 代理

let obj = {};
let newVal = '';
Object.defineProperty(obj, 'name', {
    get(){
        return newVal;
    },
    set(v){
        newVal = v;
        // this.name = v  如果这样写,,会无限触发set
    }
});
obj.name = 123;
console.log(obj.name);  // 123

1.2 Es6 代理

1.2.1 基础用法
let obj = {};
let p = new Proxy(obj,{});
obj.name = 123
console.log(p.name); // 123

1.2.2 get 方法 监听属性读取
举例说明

let dict = {
    'xx' : 'xx'
};
dict = new Proxy(dict, {
    get(target, p, receiver){
        // target : Object xx: "xx"   
        // p : 传进来的xx    
        // receiver : Proxy
        
        return '自定义条件  赛选以后返回的值';
    }
});
console.log(dict['xx']);  // 自定义条件  赛选以后返回的值
1.2.3 set方法 监听设置属性
举例 : 只能设置number类型
必须返回一个boolean类型
let dict = {
    'xx' : 'xx'
};
dict = new Proxy(dict, {
    set(target, p, value, receiver){
        console.log(target, p, value, receiver);
          return  true
        打印结果 : {xx: "xx"}  "xx"  "123"   Proxy {xx: "xx"}
    }
});
dict['xx'] = '123';
1.2.4 has方法 判断key是否在对象里面
let range = {
    start : 1,
    end : 10
};
// console.log(2 in range);  // false,此时没被代理

range = new Proxy(range, {
    has(target, p){
        console.log(target, p);  // {start: 1, end: 10} "2"
        return p >= target.start && p <= target.end;
    }
});
console.log(2 in range); //true
console.log(11 in range); //false
1.2.5 ownkeys 方法 监听循环遍历
let obj = {
    name : 'xxx',
    [Symbol('es')] : 'es6'
};
Object.getOwnPropertyNames(obj); //  ["name"]   非Symbol类型
Object.keys(obj); //  ["name"]   非Symbol类型
for(let key in obj){console.log(key);}   // name 
Object.getOwnPropertySymbols(obj); // [Symbol(es)]   Symbol

举例,,,设置以 _ 开头的字段,,为私有属性
let userName = {
    name : 'xx',
    age : 18,
    _passWord : '***'
};
userName = new Proxy(userName, {
    ownKeys(target){
        return Object.keys(target)
                     .filter(key => {
                         // console.log(key); // name  age  _passWord
                         return !key.startsWith('_');
                     });
    }
});
for(let userNameKey in userName){
    console.log(userNameKey);  // name  age
}
1.2.6 deleteProperty 方法 拦截delete方法
必须返回一个boolean类型
let userName = {
    name : 'xx',
    age : 18,
    _passWord : '***'
};
userName = new Proxy(userName, {
    deleteProperty(target, p){
        // 是否以下划线开头
        if(p.startsWith("_")){
            delete target[p]
        }
    }
});
delete userName["age"]
console.log(userName);  // {name: "xx", age: 18, _passWord: "***"}

delete userName["_passWord"]
console.log(userName);  // {name: "xx", age: 18}   
1.2.7 apply方法 拦截函数的调用,,以及call,apply等
一个求和函数
let GetSum = (...args) => {
    let num = 0;
    args.forEach(item => {
        num += item;
    });
    return num;
};

GetSum = new Proxy(GetSum, {
    apply(target, thisArg, argArray){
        console.log(target);   // GetSum函数
        console.log(thisArg);  // GetSum(1, 2): undefined
        console.log(argArray); // [1, 2] GetSum的参数
        return target(...argArray) * 2;
    }
});
GetSum(1, 2);  // 6   代理以后*2
GetSum.call(null, 1, 2);  // 6   代理以后*2    第一个参数是指向的对象
GetSum.apply(null, [1, 2, 3]);  // 12   第一个参数是指向的对象   第二个是数组
1.2.8 construct方法 拦截new
let newClass = class{
    constructor(name){
        this.name = name;
    }
};
newClass = new Proxy(newClass, {
    construct(target, argArray, newTarget){
        console.log(target);  // newClass这个的class
        console.log(argArray); // ["xx"] 参数的数组
        console.log(newTarget); // {length: 1, prototype: {…}, name: "newClass"}
        return new target('我改变了参数');
    }
});
let a = new newClass('xx');
console.log(a);  // newClass {name: "我改变了参数"}
1.2.9 proxy总结
image.png

image.png

2 Reflect反射

2.1 将Object的语法转移到Reflect上面
设计之初,很多方法都挂载在Object上面,,es6转移一部分到Reflect
Object.defineProperty  => Reflect.defineProperty
2.2 修改某些Object方法的返回值
Object.defineProperty (没有返回值) 去定义属性   如果有些属性无法被定义 :
如果不能被定义抛出异常
try{
    Object.defineProperty()
}catch(e){
}

Reflect.defineProperty有返回值(布尔类型),,,如果不能定义返回false
2.3 让Object操作变成函数行为
"assign" in Object  // true  Object下面 是否有assign这个方法
Reflect.has(Object,"assign")  // true
2.3 Reflect对象的方法和Proxy对象的方法一一对应
get set delete ownKeys
let user = {
    name : 'xx',
    _passWord : '123456'
};
user = new Proxy(user, {
    get(target, p, receiver){
        if(p.startsWith('_')){
            throw new Error('不可访问');
        } else{
            // return target[p]  和下面的这种写法一样
            return Reflect.get(target, p);
        }
    },
    set(target, p, value, receiver){
        // target[p] = value
        if(p.startsWith('_')){
            throw new Error('不可访问');
        } else{
            Reflect.set(target, p, value);
            return true;
        }
    },
    deleteProperty(target, p){
        if(p.startsWith('_')){
            throw new Error('不可访问');
        } else{
            // delete target[p]
            Reflect.defineProperty(target, p);
            return true;
        }
    },
    ownKeys(target){
        return Object.keys(target)
                     .filter(key => {
                         // console.log(key); // name  age  _passWord
                         return !key.startsWith('_');
                     });
        // 可直接把Object.keys换成  Reflect.keys
    },
});

// get
console.log(user.name); //  xx
try{
    console.log(user._passWord);
} catch(e){
    console.log(e.message);
}   //  会打印不可访问

// set
user.name = 11;
console.log(user.name);  // 11
try{
    user._passWord = 11;
} catch(e){
    console.log(e.message);
}   //  会打印不可访问

// delete 与上一致
apply
let getSum = (...args) => {
    let num = 0;
    args.forEach((item) => {
        num += item;
    });
    return num;
};
console.log(getSum(1, 2));  // 3

getSum = new Proxy(getSum, {
    apply(target, thisArg, argArray){
        // return target(...argArray) * 2;

        // 改变谁,,,改变成谁,,,参数
        return Reflect.apply(target, target, [...argArray]) * 2;
    }
});
console.log(getSum(1, 2));  // 6
console.log(getSum.apply(null, [1, 2]));  // 6

你可能感兴趣的:(ES6-11 总结六 (代理Proxy 反射Reflect))