Immutable?Mutative比Immer。js快10x倍?
大家好,很高兴又见面了,我是" 高级前端进阶 ",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
高级前端进阶1.什么是不可变性(Immutable Data)?
Immutable Data 一旦创建,就不能被更改。对 Immutable 对象的任何修改、添加或删除操作都会返回一个新的 Immutable 对象。
什么是不可变对象?图片来源:Alamy Stock Photo
Immutable 实现原理是持久化数据结构(Persistent Data Structure),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。
为了避免深度拷贝(deep Copy)把所有节点都复制一遍带来的性能损耗,Immutable 使用了共享结构(Structural Sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。如下动图所示:
2.Immer介绍?2.1 什么是Immer?
Immer 简化了不可变数据结构的处理。
Immer 可用于任何需要使用不可变数据结构的上下文。 例如与 React state、React 或 Redux reducer 或配置管理相结合。 不可变数据结构允许更改检测:如果对对象的引用没有更改,则对象本身没有更改。 此外,它使克隆更加容易:不需要复制数据树的未更改部分,并且在内存中与相同状态的旧版本共享。const updatedUser = { ...User, // Rest展开操作User来获取新的更新后的User对象,即updatedUser ed: { ...User.ed, school : { ...User.ed.school, name: "B" } } }
一般来说,这些好处可以通过确保您永远不会更改对象、数组或映射的任何属性,而是始终创建一个更改的副本来实现。 在实践中,这会导致代码编写起来非常麻烦,而且很容易意外地违反这些约束。
Immer 将通过解决这些痛点帮助您遵循不可变数据范式:Immer 将检测意外突变并抛出错误Immer 将消除对不可变对象创建深度更新时所需的典型样板代码的需要:如果没有 Immer,则需要在每个层级手动制作对象副本。 使用 Immer 时,会对draf对象进行更改,draf对象会记录更改并负责创建必要的副本,而不会影响原始对象。使用 Immer 无需学习专用 API 或数据结构。2.2 Immer如何工作?
使用 Immer,会将所有更改应用到临时草稿,它是 currentState 的代理。 完成所有更新后,Immer 将根据对草案状态的改变生成 nextState。 这意味着可以通过简单地修改数据来与数据交互,同时保留不可变数据的所有好处。
使用 Immer 就像拥有一个私人助理。 助理拿了一封信(当前状态)并给了您一份副本(草稿)以记下更改。 完成后,助手会拿走你的草稿并为你生成最终的一封信(下一个状态)。2.3 Immer使用?const baseState = [ // 基础、原始state { title: "Learn TypeScript", done: true },{ title: "Try Immer", done: false } ]
假设有上面的基本状态,需要更新第二个待办事项,并添加第三个,同时不想改变原始的 baseState,同时避免深度克隆(以保留第一个待办事项)。 2.3.1 不使用Immer
如果没有 Immer,将不得不小心地浅复制受更改影响的状态结构的每一层。 const nextState = baseState.slice( // 数组浅复制 nextState[1] = { // replace element 1... ...nextState[1], // with a shallow clone of element 1 done: true // ...combined with the desired update } // nextState被深度拷贝,push方法是安全的 // but doing the same thing at any arbitrary time in the future would // violate the immutability principles and introduce a bug! nextState.push({title: "Tweet about it"})2.3.2 使用Immer
使用 Immer,此过程更加直接。 可以利用 produce 函数,它将开始的状态作为第一个参数传递。 produce 将负责所有的复制操作,并通过冻结数据来防止未来的意外修改。import produce from "immer" const nextState = produce(baseState, draft => { // 通过produce方法操作 draft[1].done = true draft.push({title: "Tweet about it"}) })3.什么是Mutative?
Mutative是一个用于高效、不可变更新的 JavaScript 库,默认情况下比 Immer 快 10 倍,甚至比纯手工制作的 reducer 还要快。
4.为什么需要Mutative?
手动编写immutable更新通常很困难,且易出错。 Immer可以使用"可变"逻辑编写更简单的不可变更新。
但它的性能问题会导致运行时性能开销。 Immer 必须默认启用自动冻结(如果禁用自动冻结,性能会更差),Immer 的这种不可变状态并不常见。 跨进程、远程数据传输等场景不得不不断地冻结这些不可变数据。
Mutative还有很多的改进,比如更好的类型推断、非侵入式标记、支持更多类型的不变性、更安全等等。5.Mutative vs Immer性能比较
测量(操作/秒)以更新 50K 数组和 1K 对象为例,具体代码查看文末资料。 Naive handcrafted reducer - No Freeze x 3,713 ops/sec ±0.86% (89 runs sampled) Mutative - No Freeze x 5,323 ops/sec ±1.69% (93 runs sampled) Immer - No Freeze x 8 ops/sec ±0.88% (23 runs sampled) Mutative - Freeze x 875 ops/sec ±1.20% (95 runs sampled) Immer - Freeze x 320 ops/sec ±0.45% (92 runs sampled) Mutative - Patches and No Freeze x 752 ops/sec ±0.16% (96 runs sampled) Immer - Patches and No Freeze x 7 ops/sec ±1.32% (23 runs sampled) Mutative - Patches and Freeze x 425 ops/sec ±0.33% (95 runs sampled) Immer - Patches and Freeze x 239 ops/sec ±0.99% (89 runs sampled) The fastest method is Mutative - No Freeze
运行 yarn benchmark 。
操作系统:macOS 12.6,CPU:Apple M1 Max,Node.js:16.14.2
Immer 依赖于自动冻结,如果禁用自动冻结,Immer 将有巨大的性能下降,此时Mutative 有巨大的性能领先。尤其是对于大型数据结构,Mutative将有超过 50 倍的性能领先。
因此,如果使用 Immer,则必须启用自动冻结以提高性能。 Mutative 允许默认禁用自动冻结。 使用两者的默认配置,可以看到 Mutative(5,323 ops/sec)和 Immer(320 ops/sec)之间明显的性能差距。
总体而言,Mutative 在更多的性能测试场景中比 Immer 有巨大的性能领先。6.Mutative特点和优势Mutation makes immutable updates 支持打补丁(Support apply patches)可选冻结状态(Optional freezing state)自定义浅拷贝(Custom shallow copy)不可变和可变数据可标记(Immutable and mutable data markable)用于更安全的可变数据访问的严格模式(Safer mutable data access in strict mode)支持 JSON 补丁(Support for JSON patches)支持reducer(Support for reducer)7.Mutative 和 Immer 之间的区别
差别可以通过下面的图进行说明:
Mutative 和 Immer 之间的区别
除了上图的差异外,Mutative 比 Immer 有更少的错误, 经过混淆和 Gzip 压缩后, Mutative 大小为 4.16KB,而具有相同功能的 Immer 大小为 4.67 KB。
8.Mutative安装&使用8.1 安装yarn install mutative //npm install mutative8.2 使用 import { create } from "mutative"; const baseState = { foo: "bar", list: [{ text: "coding" }], }; // baseState代表基础state const state = create(baseState, (draft) => { draft.foo = "foobar"; // 作为draf传递给第二个draf函数,修改后返回新的状态 draft.list.push({ text: "learning" }); });9.本文总结
本文主要和大家介绍下 Mutative 和 Immer ,同时做了简单的对比。因为笔者也没有在生产项目中使用过Mutative 和 Immer,所以很多探索也就浅尝辄止,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。
参考资料
https://blog.csdn.net/JiaPeng366/article/details/106455221/
https://dev.to/unadlib/mutative-10x-faster-than-immer-2060
https://github.com/unadlib/mutative/blob/main/test/performance/benchmark.t
https://github.com/unadlib/mutative
https://immerjs.github.io/immer/
世界巨星驾到!中超又看上1位欧洲金靴单届世界杯独造5球!西亚联赛正在大力引进外援,随着C罗等一系列球星加盟,沙特联赛更是成为影响力第一的亚洲联赛。如今,中超联赛在全面开放球迷后也有了更大吸引力,根据意大利媒体calciomercato透
澳网阿扎伦卡晋级第四轮1月20日,阿扎伦卡庆祝比赛胜利。新华社发(胡泾辰摄)当日,在墨尔本进行的澳大利亚网球公开赛女子单打第三轮比赛中,白俄罗斯选手阿扎伦卡以2比1战胜美国选手凯斯,晋级第四轮。1月20
中国年东营味东营人春节去哪玩?这份攻略请查收东营的大街小巷年味越来越浓赶黄河大集,品东营年味小编精心汇集全市好玩好逛的去处让你嗨玩春节不停歇陪你一起过一个欢乐祥和的新春佳节大年初一,黄河元宇宙市集开街,亲水光影互动区电音舞台
皮市街禁行机动车,春节期间如何就近停车?攻略来了!新年即将到来,一只只大红灯笼一串串喜庆的彩灯装饰高高挂起,网红皮市街上春节的仪式感被拉满,烟火气里升腾着美好与活力。1月15日起,皮市街正式禁行机动车,并正式启动国家级旅游休闲街区
过年去哪玩?高明最全打卡攻略来了丨春节潮玩高明滴滴,春节的脚步越来越近了各位街坊打算去哪里玩呢?明仔的攻略已经做好了!即日起,高明融媒体中心推出春节潮玩高明8线路游攻略,通过最新最全的资讯整合,推介高明,为大家解锁假期潮玩新姿
过年七天乐,东湖最全游玩攻略来了!除夕到!又到一年团聚时,团年饭上满满的佳肴,家人之间互相祝福的话语,都包裹着浓浓的幸福,有了这些才算一个完整的年。今年春节,武汉东湖开启喜迎新春惠游东湖文旅惠民活动,20万张惠民票
新疆南北疆大环线攻略分享新疆,有大漠戈壁峡谷草原森林湖泊雪山等景观,一路自驾驰骋,各种绝美的景色在路上毫无保留地铺展在面前,是国内自驾游热门目的地。那么,新疆自驾游去哪里玩?下面给你推荐8条新疆自驾游经典
中国男篮阵容凸显四大特点,全面开启欧洲篮球的高快准之路前期,中国篮协公布的中国男篮18人大名单中,有6位新面孔!这彰显出了中国男篮新帅乔尔杰维奇对于欧洲篮球理念和选择球员的极度自信!毕竟,距离男篮世界杯只有8个月的集训时间。面对时间紧
23日梦幻1阵最佳阵容欧文完胜库里篮网神塔勇创新高北京时间1月23日,NBA共进行7场比赛。欧文小卡连续carry,两大豪门内线争相斗法,施罗德稳定发挥再度成为湖人的关键先生。下面一起来看今日最佳阵容。后场凯里欧文能量值42战力值
羽毛球印度公开赛雅思半年内两次东渡组合终结连胜1月21日,2023年世界羽联巡回赛超级750印度公开赛在新德里展开半决赛争夺。在稍早开始的有中国选手参加的三场比赛中,国羽队员发挥一般。孤身杀入四强的何冰娇未能抵挡住韩国选手安洗
再见齐达内,三下家全没!世界第一新帅确定,大罗推荐,不等他了齐达内在等待了法国队主帅将近1年多时间之后,最终还是没有能够等到德尚下课的那一天。德尚在获得了法国队世界杯后送上来的续约合同后,将会继续带领法国队征战欧洲杯,而德尚位置稳固之后,一