目录ProxyBasicSyntax(基本用法)SchemaValidation-只读SchemaValidation-检查SchemaValidation-监控和报告SchemaValidation-唯一只读idRevocableProxies-撤销代理ProxyVSObject.defineProperty()proxy监控更广泛的操作Proxy更好地支持数组对象的监控如何使用Proxy监控数组?Proxy以非侵入式的方式监督对象的读写。ES6-ES10学习布局Proxy是ES6标准中新增的一个非常强大的功能。它可以自定义一些常见的行为,例如搜索、赋值、枚举和函数。call等。从Proxy这个名字也可以看出它包含了“代理”的意思。只要有“代理”的需求,都可以考虑使用Proxy来实现。PS:类似于租房找中介,中介可以屏蔽原始信息。基本语法letp=newProxy(target,handler)parametermeaningrequiredtargettargetobjectwrappedbyProxy(可以是任何类型的对象,包括nativearray,function,甚至是另一个proxy)Yhandler是一个对象,其属性是执行时的第一个定义代理在操作期间的行为的函数Y的参数目标是用于代理的“对象”。被代理后不能直接访问,handler就是实现代理的过程。//o是房东的角色,代理对象leto={name:'xiaoming',price:190}//d是中介的角色,代理letd=newProxy(o,{})console.log(d.price,d.name)//190'xiaoming'//由于传递的是空对象,所以通过letd=newProxy(o,{get(target,key){//target指的是代理对象o,key指的是属性if(key==='price'){//如果等于price,则加20returntarget[key]+20}else{returntarget[key]}}})console.log(d.price,d.name)//210"xiaoming"leto={name:'xiaoming',age:20}console.log(o.name)//xiaomingconsole.log(o.age)//20console.log(o.from)//undefined//当我们读取from时,因为o中没有这个属性,所以返回undefined,如果我们不想在调用时出现undefined//ES5处理方式//console.log(o.from||'')//ES6处理leto={name:'xiaoming',age:20}lethandler={get(obj,key){returnReflect.has(obj,key)?obj[key]:''}}letp=newProxy(o,handler)console.log(p.from)//''SchemaValidation——只读并在不影响Application中原有数据的情况下进行备份ES5leto={name:'xiaoming',price:190}for(let[key]ofObject.entries(o)){Object.defineProperty(o,key,{writable:false})}console.log(o.name,o.price)//xiaoming190o.price=300console.log(o.name,o.price)//xiaoming190ES6leto={name:'xiaoming',price:190}letd=newProxy(o,{get(target,key){returntarget[key]},set(target,key,value){returnfalse}})//只读不写d.price=300console.log(d.price,d.name)//190“xiaoming”和proxy的区别是全锁了,但是在ES6中,用户只能读,但是proxy可以操作SchemaValidation——检查判断如果价格>300,则不允许修改。如果没有该属性,则返回空字符串leto={name:'xiaoming',price:190}letd=newProxy(o,{get(target,key){returntarget[key]||''},set(target,key,value){if(Reflect.has(target,key)){if(key==='price'){if(value>300){returnfalse}else{目标[key]=value}}else{target[key]=value}}else{returnfalse}}})d.price=280console.log(d.price,d.name)//280"xiaoming"d.price=301//没有生效,因为验证失败d.name='xiaohong'console.log(d.price,d.name)//280"xiaohong"d.age=40//没有这个属性,设置时返回,get时赋空字符串getconsole.log(d.price,d.name,d.age)//280"xiaohong"""去掉耦合,将validationfunction分离成validationfunctionleto={name:'xiaoming',price:190}letvalidator=(target,key,value)=>{if(Reflect.has(target,key)){if(key==='price'){if(value>300){returnfalse}else{target[key]=value}}else{target[key]=value}}else{returnfalse}}letd=newProxy(o,{get(target,key){returntarget[key]||''},set:validator})d.price=280console复制代码.log(d.price,d.name)//280"小明"d.price=301d.name='小红'console.log(d.price,d.name)//280"小红"d.age=40console.log(d.price,d.name,d.age)//280"xiaohong"""组织成一个组件//validator.jsexportdefault(obj,key,value)=>{if(Reflect.has(key)&&value>20){obj[key]=value}}importValidatorfrom'./Validator'letdata=newProxy(responsese.data,{set:Validator})SchemaValidation——监控并报告window.addEventListener('error',(e)=>{console.log(e.message)//report//report('...')},true)//捕获leto={name:'xiaoming',price:190}letvalidator=(target,key,value)=>{if(Reflect.has(target,key)){if(key==='price'){if(value>300){//不满足触发错误thrownewTypeError('priceexceeded300')}else{target[key]=value}}else{target[key]=value}}else{returnfalse}}letd=newProxy(o,{get(target,key){returntarget[key]||''},set:validator})d.price=280console.log(d.price,d.name)//280"xiaoming"d.price=301d.name='xiaohong'console.log(d.price,d.name)//280"xiaoming"d.age=40console.log(d.price,d.name,d.age)//280"xiaohong"""SchemaValidation——唯一只读id每次生成一个id,不可修改每个实例的id各不相同other//探索一个类Component{constructor(){this.id=Math.random().toString(36).slice(-8)}}letcom=newComponent()letcom2=newComponent()for(leti=0;i<10;i++){console.log(com.id)}for(leti=0;i<10;i++){控制台。log(com2.id)}com.id='abc'console.log(com.id,com2.id)//这个方法可以每次生成一个id,但是可以修改,不符合要求//(10)4robfncs//(13)93ukz26i//可以修改//abc93ukz26i//Exploration2classComponent{getid(){returnMath.random().toString(36).slice(-8)}}letcom=newComponent()letcom2=newComponent()for(leti=0;i<10;i++){console.log(com.id)}for(leti=0;i<10;i++){console.log(com2.id)}com.id='abc'console.log(com.id,com2.id)//这个方法不能修改,但是每次都会生成一个新的,不满足要求//nqwlamib//l9ojsjiq//gad3vm2a//i1jew3bd//owquntob//rcpce268//va6mry5v//lvqxv0m4//a900358x//jahi7079//vukusf5k//rg8hyzf3//50vxv0hk////tjeyes1c/bx1vz////v9k2v7hd//0mgn3heb//n0zc9v66//rdjevl2i//9rjmwrd9kxdxtywe//探索三个类组件{constructor(){this.proxy=newProxy({id:Math.random().toString(36).slice(-8)},{})}getid(){returnthis.proxy.id}}letcom=newComponent()letcom2=newComponent()for(leti=0;i<10;i++){console.log(com.id)}for(leti=0;i<10;i++){console.log(com2.id)}com.id='abc'console.log(com.id,com2.id)//满足要求//(10)e9e8jsks//(10)tfs2rrvg//e9e8jskstfs2rrvgRevocableProxies——除了常规代理外,还可以创建临时代理。临时代理可以被撤销。临时代理的作用。leto={name:'xiaoming',price:190}//这里不能用new,只能用Proxy.revocable声明代理letd=Proxy.revocable(o,{get(target,key){if(key==='price'){returntarget[key]+20}else{returntarget[key]}}})//d包含代理数据和撤销操作console.log(d.proxy.price)//210console.log(d)//{proxy:Proxy,revoke:?}setTimeout(function(){//撤销代理d.revoke()setTimeout(function(){console.log(d.proxy.price)//UncaughtTypeError:Cannotperform'get'onaproxythathasbeenrevoked},100)},1000)ProxyVSObject.defineProperty()如果要监听对象属性的变化,可以使用Object.defineProperty添加属性的方法,则可以捕获对象中读写属性的过程。VUE3.0之前的版本就是通过这个实现数据的双向绑定。从VUE3.0开始就使用Proxy来实现内部响应。代理是专门为对象设置的,所以代理可以方便的监控对象的读写过程。与defineProperty相比,proxy功能更强大,使用起来也更方便。1.代理监控更广泛的操作。defineProperty只能监听属性的读写,proxy可以监听更多对象的操作,比如删除属性。constperson={name:'xm',age:20}constpersonProxy=newProxy(person,{deleteProperty(target,property){console.log('delete'+property)//删除年龄deletetarget[property]}})deletepersonProxy.ageconsole.log(person)//{name:'xm'}handlermethodtriggermethodget读取属性set写入属性hasinoperatordeletePropertydeleteoperatorgetPropertyObject.getPropertyOf()setPropertyObject.setPrototypeOf()isExtensibleObject.isExtensible()preventExtensionsObject.preventExtensions()getOwnPropertyDescriptorObject.getOwnPropertyDescriptor()definePropertyObject.defineProperty()ownKeysObject.keys(),Object.getOwnPropertyNames(),Object.getOwnPropertySymbols()applycallafunctionconstructcallafunctionwithnew2.Proxy更好的支持监控过去对象中的数组对象。defineProperty()使用改写数组的操作方式。如何使用Proxy监控阵列?constlist=[]constlistProxy=newProxy(list,{set(target,property,value){console.log('set',property,value)target[property]=valuereturntrue//表示设置成功}})listProxy.push(100)//set0100//setlength1listProxy.push(200)//set1200//setlength23.proxy在一个非侵入式方式监督对象的读写ES6-ES10学习布局
