You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
letobj={name: 'wozien',_age: 12};letproxy=newProxy(obj,{ownKeys(target){returnReflect.ownKeys(target).filter(key=>{returntypeofkey!=='string'||key[0]!=='_';});}});for(letkeyinproxy){console.log(key);}// name
letobj={name: 'wozien'};let{ proxy, revoke }=Proxy.revocable(obj,{});console.log(proxy.name);// wozienrevoke();console.log(proxy.name);// Cannot perform 'get' on a proxy that has been revoked
应用
监测数组
我们知道在es5中无法检测数组的存取行为,利用 Proxy 可以轻松完成这个任务:
letproxy=newProxy([],{get(arr,key){console.log('proxy get '+key);returnarr[key];},set(arr,key,val){console.log('proxy set '+key+': '+val);return(arr[key]=val);}});proxy[0]=1;console.log(proxy[0]);// proxy set 0: 1// proxy get 0// 1
functiondefine(obj,key){letvalue=obj[key];Object.defineProperty(obj,key,{get(){console.log('get obj prop '+key);returnvalue;},set(newVal){console.log('set obj prop '+key+' to '+newVal);value=newVal;}});}functionobserver(obj){for(letkeyinobj){define(obj,key);}}letobj={name: 'wozien',age: 23};// 侦测obj数据observer(obj);obj.name;obj.name='marry';obj.age=25;// get obj prop name// set obj prop name to marry// set obj prop age to 25
classPerson{constructor(name,age){this.name=name;this.age=age;returnnewProxy(this,{set(target,key,value){if(typeofvalue!==Person.propTypes[key]){thrownewTypeError('property type error');}returnReflect.set(target,key,value);}});}}Person.propTypes={name: 'string',age: 'number'};letperson=newPerson('wozien',12);person.name=12;// throw new TypeError('property type error');
我们知道在es5中
Object.definePropety()
方法可以设置对象属性的getter
和setter
,从而拦截对象属性的存取行为。但是局限性挺大,比如无法拦截数组的存取和其他对象的行为比如(in
和delele
等)。于是,es6引入了代理(Proxy
),它是一种可以拦截并改变底层js操作的包装器。基本用法
用
new Proxy(target, handler)
新建一个代理对象,target
表示代理的目标对象,handler
是一个拦截行为的配置对象。当
handler
是个空对象时,代理只是简单的转发目标的默认行为。es6为我们提供了13种拦截行为的配置,并用Reflect
对象提供操作JS的默认行为。比如用
get()
拦截代理对象的值的获取行为:用
set()
设置代理对象的值设置行为:使用
has()
设置代理对象in
操作行为,比如隐藏对象的某些属性:使用
ownKeys()
设置拦截对象的Object.keys()
,for...in
等操作的行为:其他更多的代理拦截行为设置参考Proxy-MDN
可撤销代理
利用
Proxy.revocale()
方法创建可以撤销的代理对象。该方法返回一个含有下面两个属性的对象:调用
revoke()
方法后,代理对象不能进一步操作:应用
监测数组
我们知道在es5中无法检测数组的存取行为,利用
Proxy
可以轻松完成这个任务:替代Object.defineProperty()
Object.defineProperty()
是监测对象的属性存取,如果要使整个对象可监测,就要循环设置:利用
Proxy
的set()
和get()
设置拦截对象的存取行为:模拟数组行为
我们知道数组可以通过设置不存在的索引扩大数组长度,通过设置小于数组长度时可以删除元素。在es5我们无法用对象模拟这种行为,而利用
Proxy
可以实现:监测类属性类型
可以在类构造函数中返回实例对象的代理,代理可以在
set()
监测对象属性值的类型:参考
ES6 系列之 defineProperty 与 proxy
The text was updated successfully, but these errors were encountered: