题说proxy

昨天在和群友讨论时遇到一题是这样的。

题目描述

//Tomy非常敏感,不喜欢别人碰他的东西。一旦有人碰他就会大喊Don't Touch Me.
//完成tomy这个对象,禁止对tomy的内容进行修改(增加、修改、删除)
//一旦有人对tomy进行任何的修改,调用console.log打印Don't Touch Me
const tomy={
    name:"lizhiqiang",
    age:"23"
};

 

题目分析

刚开始我觉得可以通过es5中的defineProperty去定义访问器属性,当要修改tomy的属性时,就可以console.log信息出来。

可是这样的话无法做到当要删除属性时,以及要增加属性时,console.log信息。也就是说defineProperty提供给我们的权限还不够,我们需要更加底层的操作。

那么要怎么做呢?

只能使用ES6中的proxy来做啦。

题目要求我们在修改之前console信息,也就是需要我们拦截下修改操作,并在此之前console信息。

 

proxy简介

通过调用 new Proxy() ,你可以创建一个代理用来替代另一个对象(被称为目标),这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当作同一个对象来对待。

代理允许你拦截在目标对象上的底层操作,而这原本是 JS 引擎的内部能力。拦截行为使用了一个能够响应特定操作的函数(被称为陷阱)。

 被 Reflect 对象所代表的反射接口,是给底层操作提供默认行为的方法的集合,这些操作是能够被代理重写的。每个代理陷阱都有一个对应的反射方法,每个方法都与对应的陷阱函数同名,并且接收的参数也与之一致。下表总结了这些行为:

 

好了,针对题目要求,我们只需要写代理陷阱set、deleteProperty就行。

 

代码

//Tomy非常敏感,不喜欢别人碰他的东西。一旦有人碰他就会大喊Don't Touch Me.
//完成tomy这个对象,禁止对tomy的内容进行修改(增加、修改、删除)
//一旦有人对tomy进行任何的修改,调用console.log打印Don't Touch Me
const tomy={
    name:"lizhiqiang",
    age:"23"
};
let tomyProxy=new Proxy(tomy,{
    deleteProperty(trapTarget,key){
        console.log("Don't Touch Me--delete "+key);
        return false;
    },
    set(trapTarget, key, value, receiver) {
        if (!trapTarget.hasOwnProperty(key)) {
            console.log("Don't Touch Me--add "+key);
        }else{
            console.log("Don't Touch Me--update "+key);
        }
        return false;
    }
});
console.log(tomyProxy);
Object.freeze(tomyProxy);
delete tomyProxy.age;//删除属性
console.log(tomyProxy);
tomyProxy.age=1;//修改属性
console.log(tomyProxy);
tomyProxy.phone="123456789";//增加属性
console.log(tomyProxy);

运行结果如下,可见这样是可行的。

其实es6的proxy和symbol还有很多值得深入学习的呀,以后会慢慢练习使用。

 

posted @ 2018-04-17 13:50  汕大小吴  阅读(285)  评论(0编辑  收藏  举报