taobowen / rainbow-fart

🌈前端面试彩虹屁合集
4 stars 0 forks source link

getter、setter、代理 #19

Open taobowen opened 5 years ago

taobowen commented 5 years ago

getter、setter

  第一次接触getter、setter是在vue的双向绑定的类源码中,在Object.defineProperty里定义getter、setter,那时对getter、setter在发布-订阅设计模式中扮演的角色有了一个粗浅的了解。简单的来说,getter、setter可以控制对象中属性的访问,而定义getter、setter有三种方法:

代理

  代理是我们通过代理控制对另一个对象的访问。可以将代理理解为通用化的setter与getter,区别是每个setter与getter仅能控制单个对象属性,而代理可用于对象交互的通用处理,包括调用对象的方法。   废话少说,上代码:

const emperor={name:"taobowen"};//emperor是目标对象
const reprentative=new Proxy(emperer,{//通过Proxy构造器创建代理,传入对象emperor,以及包含get与set方法的对象,用于处理对象属性的读写操作
    get:(target,key)=>{
        console.log("reading"+key+"through a proxy");
        return key in target?target[key]:"don't bother the emperor";
    },
    set:(target, key, value) =>{
        console.log("writing"+key+"thrrough a proxy");
        target[key]=value;
    }
});
//分别通过目标对象和代理对象访问name属性
if(emperor.name==="taobowen"){
    console.log("the emperor's name is taobowen");
}
if(reprentative.name==="taobowen"){
    console.log("we can get the name property through a proxy");
}
//直接访问目标对象上不存在的nickname属性将返回undefined
if(emperor.nickname===undefined){
    console.log("the emperor doesn't have a nickname");
}
//通过代理对象访问时,将会检测到nickname属性不存在,并返回警告
if(reprentative.nickname==="don't bother the emperor"){
    console.log("the proxy jumps in when we make inproper requests");
}
//通过代理对象添加nickname属性后,分别通过目标对象和代理对象均可访问nickname属性
reprentative.nickname="Tenno";
if(emperor.nickname==="Tenno"){
    console.log("the emperor now has a nickname");
}
if(reprentative.nickname==="Tenno"){
    console.log("the nickname is alse accessible through the proxy");
}

  在使用内置的Proxy构造函数时,它可以接受两个参数,第一个是目标对象,在例子中是emperor,第二个是一个对象,该对象内定义了再对象执行特定行为时触发的函数。而关于定义各种对象行为的内置方法如下:

下面列举使用代理的一些常见应用:

最后,要注意的一点是,尽管使用代理可以创造性地控制对象的访问,但是大量的控制操作将会带来性能问题,因此我们还是要谨慎使用代理。