1、什么是Immutable
Immutable是指一旦创建即不可变的数据,所有对Immutable对象进行的修改操作最终都会返回一个新的Immutable对象。其中实现的原理是持久化数据结构(Persistent Data Structure),即使用旧的数据创建新数据时保持旧的数据不变。
现有的Immutable库主要有三种:immutable、immer、seamless-immutable。
2、immutable.js
Facebook 工程师 Lee Byron 花费 3 年时间打造,与 React 同期出现,但没有被默认放到 React 工具集里(React 提供了简化的 Helper)。它内部实现了一套完整的 Persistent Data Structure,还有很多易用的数据类型。像 `Collection`、`List`、`Map`、`Set`、`Record`、`Seq`。有非常全面的`map`、`filter`、`groupBy`、`reduce``find`函数式操作方法。同时 API 也尽量与 Object 或 Array 类似。https://zhuanlan.zhihu.com/p/20295971
immutable.js支持的数据类型主要有
(1)Map:键值对集合,对应于Object,类似ES6中的Map
(2)List:有序可重复列表,对应Array
(3)Set:无序不可重复列表
同时immutable还提供了丰富的API对数据进行操作,不管是简单的对象、数组还是有嵌套结构的数据,都能快速地对数据进行修改
3、why immutable?
背景
与immutable相对应的即mutable(可变的),JavaScript中的数据都是可变的,尤其针对引用类型的数据,创建对象和数组后对其进行修改,返回还是指向原对象的指针,这样的设计是出于节约内存的考虑。然而mutable带来的负作用也是明显的,实际react项目中的数据流日趋复杂,redux中维护的state已经不是简单的对象和数组,通常是多层嵌套的数据结构。在经过多次action对state的操作后,结构复杂的state会变得难以控制,经常会引起一些自身state没有改变的组件重新渲染,这会对性能造成不小的影响,相比起来mutable节约内存的优点也就显得微不足道。
再者,redux中的reducer是纯函数,即在原始state的基础上返回一个新的state,而不是在旧的state上进行修改:
- Redux 的 combineReducers 方法 浅比较 它调用的 reducer 的引用是否发生变化。
- React-Redux 的 connect 方法生成的组件通过 浅比较根 state 的引用变化 与 mapStateToProps 函数的返回值,来判断包装的组件是否需要重新渲染
而要做到不可变数据结构,解决方案有**深拷贝、引入immutable数据。
深拷贝
深拷贝就是生成一份完全相同,但没有地址共享的数据。这样做的代价通常是非常昂贵的,深拷贝的实现需要遍历数据的每个节点,递归调用自身函数实现,而项目中需要操作的数据体量大,且多为深层嵌套的结构,这样做无疑会对性能造成严重损耗。所以深拷贝方案不可取!
immutable
immutable为了避免深拷贝带来的性能损耗,采用结构共享(Structure share)实现对数据的独立拷贝。即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。这样既可以用最小的代价实现对数据的独立拷贝,也不会对内存造成太大负担。
再者,shouldComponentUpdate是react项目优化中的一个重点。我们在比较state和props后返回true or false判断组件是否需要重新渲染,这里也需要对每个数据结构进行深层次的比较才能返回正确的结果,否则会造成组件不必要的更新或者没有按照既定情况更新。针对这种情况immutable为我们提供了immutable.is这个API,可以在性能较好的情况下实现immutable对象的深度比较。
由此可见,在项目中引入immutable是可以以较小代价优化性能的选择。
4、总结
immutable的优点
- 降低mutable带来的复杂度,实现数据的可追溯
- 节约内存(结构共享)
- 与函数式编程理念高度契合
缺点
- immutable.js库体积较大,引入项目会增加资源文件大小
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。