0
点赞
收藏
分享

微信扫一扫

1.20(Proxy、Reflect、异步)

1.20(Proxy、Reflect、异步)

一、代理

1、es5代理

let obj1 = {};
let newVal = '';
Object.defineProperty(obj1, 'name', {
    get () {
        return newVal;
    },
    set (val) {
        console.log(val);//es
        newVal = val;
    }
})
obj1.name = 'es';
console.log(obj1.name);//es

2、Proxy(代理对象,配置)

let obj2 = {};
let p = new Proxy(obj2, {});
p.name = 'wuyan';
console.log(obj2.name);//wuyan
for(let key in obj2) {
    console.log(key);//name
}

2.1 数组代理方式

let arr1 = [7, 8, 9];
arr1 = new Proxy(arr1, {
    // 钩子函数get
    get(target, prop) {
        console.log(target, prop);
        //[7, 8, 9] "2"
        //[7, 8, 9] "10"
        //如果索引在数组里有对应的值则返回,否则报错
        return prop in target ?target[prop]: 'error';
    },
})
// 想获取对象里的属性时,代理就会使用get来处理
console.log(arr1[2]);//9
console.log(arr1[10]);//error


let arr2 = [];
arr2 = new Proxy(arr2, {
    //钩子函数set
    set(target, prop, val) {
        if(typeof val === 'number') {
            target[prop] = val;
            return true;
        } else {
            return false;
        }
    }
})
arr2.push(5);
arr2.push(6);
console.log(arr2[0],arr2[1],arr2.length);

2.2 对象代理

let dict = {
    'hello':'你好',
    'world':'世界'
}
dict = new Proxy(dict, {
    get (target, prop) {
        return prop in target ?target[prop] : prop;
    }
}) 
console.log(dict['hello']);//你好

2.3 has

let range = {
    start:1,
    end:5
}
range = new Proxy(range, {
    has(target, prop) {
       return prop >= target.start && prop <= target.end;
    }
})

console.log(2 in range);//true
console.log(9 in range);//false

//ownKeys 对于循环遍历进行拦截操作
let obj3 = {
    name:'wuyan',
    [Symbol('es')]:'es6'
}
console.log(Object.getOwnPropertyNames(obj3));//name
console.log(Object.getOwnPropertySymbols(obj3));//Symbol(es)
console.log(Object.keys(obj3));//name
for(let key in obj3) {
    console.log(key);//name
}

let userinfo = {
    username:'wuyan',
    age:22,
    _password:'***'
}
userinfo = new Proxy(userinfo, {
    // 循环
    ownKeys(target) {
        // Object.keys()取出对象属性
        //filter()返回符合func条件的元素数组
        // 这边不返回_password
        return Object.keys(target).filter(key => !key.startsWith('_'));
    }
})

for(let key in userinfo){
    console.log(key);//1、username  2、age
}

console.log(Object.keys(userinfo));//[username, age]

2.4 整合起来


let user = {
    name:'wuyan',
    age:34,
    _password:'******'
}
user = new Proxy(user, {
    //需求:不能对_password进行任何操作
    //get
    get(target, prop) {
        if(prop.startsWith('_')) {
            /* throw语句用来抛出一个用户自定义的异常。当前函数的执行将被
            停止(throw之后的语句将不会执行),并且控制将被传递到调用
            堆栈中的第一个catch块。如果调用者函数中没有catch块,程序
            将会终止。 */
            throw new Error('不可访问');
            /* 
            通过Error的构造器可以创建一个错误对象。当运行时错误产生时,
            Error的实例对象会被抛出。Error对象也可用于用户自定义的异常
            的基础对象。下面列出了各种内建的标准错误类型。
            */
        } else {
            return target[prop];
        }
    },
    //set
    set (target, prop, val) {
        if(prop.startsWith('_')) {
            throw new Error('不可修改');
        } else {
            target[prop] = val;
            return true;
        }
    },
    //delete
    deleteProperty(target, prop) {
        if (prop.startsWith('_')) {
            throw new Error('不可删除');
        } else {
            delete target[prop];
            return true;
        }
    },
    //repeat
    ownKeys(target) {
        return Object.keys(target).filter(key => !key.startsWith('_'));
    }
}) 
console.log(user.age);//34
//console.log(user._password);

user.age = 22;
console.log(user.age);//22

try {
    user._password = 222;
} catch (error) {
    console.log(error.message);//不可修改
}

try {
    delete user._password;
} catch (error) {
    console.log(error.message);//不可删除
}

for(let key in user) {
    console.log(key);//name age
}

2.5 apply

let sum = (...args) => {
    let num = 0;
    args.forEach(item => {
        num += item;
    })
    return num;
}

sum = new Proxy(sum, {
    apply(target, ctx, args) {
        return target(...args) * 2;
    }
})

console.log(sum(1, 2));//6
console.log(sum.call(null, 1, 2, 3));//12
console.log(sum.apply(null, [1, 2, 3]));//12

2.6 construct new

let User = class {
    constructor(name) {
        this.name = name;
    }
}
User = new Proxy(User, {
    construct(target, args, newTarget) {
        console.log('拦截被执行');
        return new target(...args);
    }
})

console.log(new User('wuyan'));

二、反射

1、将Object方法转到Reflect上(ES5)

let obj1 = {};
let newVal = '';
Reflect.defineProperty(obj1, 'name', {
    get () {
        return newVal;
    },
    set (val) {
        console.log(val);//es
        newVal = val;
    }
})
obj1.name = 'es';
console.log(obj1.name);//es

2、修改某些Object方法的返回结果,让其变得更合理

// try {
//     Object.defineProperty()
// } catch (e) {}

// if(Reflect.defineProperty()){//boolean

// } else {

// }

3、让Object操作变成函数行为(ES6)

let user = {
    name:'wuyan',
    age:34,
    _password:'******'
}
user = new Proxy(user, {
    //需求:不能对_password进行任何操作
    //get
    get(target, prop) {
        if(prop.startsWith('_')) {
            /* throw语句用来抛出一个用户自定义的异常。当前函数的执行将被
            停止(throw之后的语句将不会执行),并且控制将被传递到调用
            堆栈中的第一个catch块。如果调用者函数中没有catch块,程序
            将会终止。 */
            throw new Error('不可访问');
            /* 
            通过Error的构造器可以创建一个错误对象。当运行时错误产生时,
            Error的实例对象会被抛出。Error对象也可用于用户自定义的异常
            的基础对象。下面列出了各种内建的标准错误类型。
            */
        } else {
            // return target[prop];
            return Reflect.get(target, prop);
        }
    },
    //set
    set (target, prop, val) {
        if(prop.startsWith('_')) {
            throw new Error('不可修改');
        } else {
            Reflect.set(target, prop, val);
            return true;
        }
    },
    //delete
    deleteProperty(target, prop) {
        if (prop.startsWith('_')) {
            throw new Error('不可删除');
        } else {
            Reflect.deleteProperty(target,prop);
            return true;
        }
    },
    //repeat
    ownKeys(target) {
        return Reflect.ownKeys(target).filter(key => !key.startsWith('_'));
    }
}) 
console.log(user.age);//34
//console.log(user._password);
try {
    console.log(user._password);
} catch (error) {
    console.log(error.message);
}

try {
    user._password = 'xxx';
} catch (error) {
    console.log(error.message);
}

try {
    delete user._password;
} catch (error) {
    console.log(error.message);
}

for(let key in user) {
    console.log(key);
}

4、Reflect对象的方法与Proxy对象的方法一一对应

let sum = (…args) => {
let num = 0;
args.forEach(item => {
num += item;
})
return num;
}

sum = new Proxy(sum, {
apply(target, ctx, args) {
return Reflect.apply(target, target, […args]) * 2;
}
})

console.log(sum(1, 2));//6
console.log(sum.call(null, 1, 2, 3));//12
console.log(sum.apply(null, [1, 2, 3]));//12

[自学中,有错误欢迎指正]

举报

相关推荐

0 条评论