当前位置: 首页 > Web前端 > vue.js

理想的JavaScript不可变数据结构

时间:2023-04-01 02:01:36 vue.js

1.介绍Immer(德语:always)是一个小包,它允许您以更方便的方式处理不可变状态。Immer提供了更方便的不可变状态操作方法二.核心优势方便主要体现在:只有一个(核心)API:produce(currentState,producer:(draftState)=>void):nextState不引入额外的数据结构:没有List,Map,Set等自定义数据结构,所以不需要特殊的相等比较方式数据操作完全基于类型:使用纯原生API操作数据,直观如:constmyStructure={a:[1,2,3],b:0};constcopy=produce(myStructure,()=>{//无事可做});constmodified=produce(myStructure,myStructure=>{myStructure.a.push(4);myStructure.b++;});copy===myStructure//truemodified!==myStructure//trueJSON.stringify(modified)===JSON.stringify({a:[1,2,3,4],b:1})//trueJSON.stringify(myStructure)===JSON.stringify({a:[1,2,3],b:0})//true与Immutable提供的全套数据结构和操作API相比:const{Map}=require('immutable');constoriginalMap=Map({a:1,b:2,c:3});constupdatedMap=originalMap.set('b',1000);//新实例,离开gtheoriginalimmutable.updatedMap!==originalMap;constanotherUpdatedMap=originalMap.set('b',1000);//尽管两者的结果相同,但都创建了一个新的reference.anotherUpdatedMap!==updatedMap;//但是两者的值相等。anotherUpdatedMap.equals(updatedMap);Immer显得过于简洁3.实现原理的两个关键点:Copy-on-write和ProxyCopy-on-write概念Copy-on-write(CoW或COW),有时也称为隐式共享或阴影,是一种资源-计算机编程中使用的管理技术,可有效地对可修改资源执行“复制”或“复制”操作。Copy-on-write(CoW或简称COW),也称为隐式共享或影子,是计算机编程中的一种资源管理技术,用于高效地复制或复制可修改的资源如果一个资源被复制但没有被修改,则不需要创建新资源;资源可以在副本和原件之间共享。修改仍然必须创建一个副本,因此技术:复制操作被推迟到第一次写入。通过sharing资源以这种方式,可以显着减少未修改副本的资源消耗,同时增加资源修改操作的小开销。具体来说,如果一个资源被复制但没有被修改,则不需要创建这个新的资源,此时副本可以和原来共享相同的资源,修改的时候还是需要创建一个副本。因此,关键是:推迟复制操作,直到第一次写入。以这种方式共享资源可以显着减少未更改副本的资源消耗,但只会略微增加资源修改操作的开销。COW策略主要用在以下几个方面:虚拟内存管理:进程共享虚拟内存、fork()系统调用及其他存储:逻辑卷管理、文件系统、数据库快照编程语言:PHP、Qt中的多种数据类型数据结构:实现不可变数据结构,如状态树以fork()系统调用为例:通过COW机制实现进程间内存共享,按需复制Immer和Copy-on-write在Immer中,Copy-on-write机制用来解决复制数据结构带来的性能负担,如下图所示:只有当数据发生变化时(write)复制数据结构(copy),否则共享同一个,所以:copy===myStructure//truemodified!==myStructure//trueProxyProxy提供了一种Hook原生数据操作API的方式,例如:constdata={a:1};constproxy=newProxy(data,{set(target,key,value,receiver){console.log(`Setkey=${key},value=${value}`);返回Reflect.set(目标、键、值、接收者);}});proxy.a=2;//outputSetkey=a,value=2data.a===2//true不仅可以监听数据变化,还可以允许操作拦截,甚至重定向:constdata={一个:1};常量副本={};constp=newProxy(data,{set(target,key,value,receiver){//不写回数据//returnReflect.set(target,key,value,receiver);//全部写入复制Reflect.set(copy,key,value,copy);}});p.a=2;data.a===1//truecopy.a===2//真的找到了什么?这样,数据就变成了不可变的数据结构P.S.Proxy语法和应用场景详见proxy(代理机制)_ES6Note9Copy-on-write+Proxy回到原来的例子:constmodified=produce(myStructure,myStructure=>{myStructure.a.push(4);我的结构.b++;});我们尝试通过魔法结合代理和写时复制:functionproduce(data,producer){letcopy;constcopyOnWrite=value=>{copy=Object.assign({},value);};constproxy=newProxy(data,{set(target,key,value,receiver){//copy-on-write!copy&©OnWrite(data);//全部写入复制Reflect.set(copy,key,value,复制);}});生产者(代理);返回副本||数据;}注意,这里提供的produce实现只是为了说明Immer的原理,存在简单的bug,获取核心API没有实际价值数据上面的proxy叫做Draft(草稿):很形象,在draft上的修改(即对draftState的修改,会按照Copy-on-write机制进行复制)不会影响源数据。草稿完成后(即执行制作者),根据草稿对源数据进行打补丁得到新数据,设计的非常巧妙,就像Photoshop中的图层操作一样:打开图片新建图层,在新图层上绘画并合并图层参考Copy-on-writeZFSAdministration,PartIX-Copy-on-writeImmer:Immutabilitytheeasyway如果你有收获又迷茫,关注“前后端”微信真的不错公众号,你会得到一个系列“原创”高质量技术文章,主题包括但不限于前端、Node.js、服务端技术