当前位置: 首页 > 科技观察

JavaScript代理对象

时间:2023-03-21 00:47:59 科技观察

JavaScript长期以来一直支持setter和getter。它们使用带有set和get关键字的简单语法来拦截对象属性访问和值修改操作。constobj={propValue:1,getprop(){console.log("Retrievingpropertyprop");returnthis.propValue;},setprop(value){console.log("Settingpropertypropto",value);this.propValue=value;}};obj.prop;//1|[inconsole]Retrievingpropertypropobj.prop=2;//[inconsole]Settingpropertypropto21234567891011121314但是,setter/getter有几个缺点:它们仅限于get和get操作(很明显)。它们不能与同一键的数据条目一起使用(即“常规”属性)。它们不是动态的,必须在使用静态Object.defineProperty()方法或使用计算值(仅限新浏览器)的对象声明期间显式应用于每个属性。//...Object.defineProperty(obj,"anotherProp",{get(){/*Dosomethingonget*/},set(value){/*Dosomethingonset*/}});123456789所以setters和getters不适用观察整个对象或执行非常简单的操作。因此,ECMAScript6(ES6)引入了代理对象(Proxyobject)。代理(Proxy)代理是一个内置的JS对象,可以用来拦截和改变与该对象相关的不同操作的行为。constoriginalObj={prop:1,anotherProp:"value"};constproxyObj=newProxy(originalObj,{get(obj,prop){console.log("Retrievingproperty",prop);returnobj[prop];},set(obj,prop,value){console.log("Settingproperty",prop,"to",value);obj[prop]=value;returntrue;}});originalObj.prop;//1originalObj.prop=2;proxyObj.prop;//2|[inconsole]Retrievingproperty"prop"proxyObj.anotherProp="newvalue";//[inconsole]Settingproperty"anotherProp"to"newvalue"1234567891011121314151617很快我们就可以看出Proxy和setters和getters的区别了。它们不仅在语法上不同(Proxy更冗长),而且在它们与原始对象的交互方式上也不同。Proxy创建一个新的对象供你交互,而不是和原来的对象交互,使用setters/getters时直接修改。在使用代理的情况下,原始对象(也称为目标)用作一种存储。你对它做的任何事情都会直接影响代理,但不会触发它的任何陷阱。代理的陷阱是一种在执行特定操作时调用的简单方法。它们都在单个处理程序对象上定义,然后传递给Proxy构造函数。除此之外,它们不仅限于set()和get(),还包括一些有趣的操作,您可以在MDN文档中找到这些操作。可撤销代理如果出于某种原因您以后想要取消或撤销代理,您应该使用静态Proxy.revocable()方法创建它。//...constrevocableProxyObj=Proxy.revocable(originalObj,{get(obj,prop){/*Dosomethingonget*/},set(obj,prop,value){/*Dosomethingonset*/}});constproxy=revocableProxyObj。proxy;proxy.prop;//OKrevocable.revoke();proxy.prop//TypeError12345678910111213该方法不直接返回Proxy对象,而是返回一个包含proxy属性下的实际Proxy的对象和一个额外的revoke()方法。调用时,此方法会使代理无效,导致以后的任何调用都以TypeError结束。然后代理将自动“收集垃圾”,释放内存空间。UseCasesProxy让您可以做的不仅仅是setter/getter。它们更快(声明后)和更灵活,使它们成为状态管理等用例的理想解决方案。Proxy带来了很多可定制性,让开发人员可以控制JS的某些元功能。所以它们不向后兼容,并且不存在完全兼容的polyfill选项。话虽如此,根据CanIuse...,整体支持看起来不错,覆盖率约为93%(不支持IE和Safari<10的版本)。