var obj = {
count: 1,
list: [1, 2, 3, 4, 5]
}
var map1 = Immutable.fromJS(obj);
var map2 = map1.set('count', 2);
console.log(map1.list === map2.list); // true
在React.js中使用Immutable Data
PureRenderMixin
当我们说一个 React component 是 pure render,是指它的 render function 是 pure function。
Pure render 的好处之一就是可以在 shouldComponentUpdate 中做性能优化。最常見的做法就是用 shallow equal 检查 props 和 state 有无改变,有改变才 update component。
shouldComponentUpdate
当一个 React 组件的 props 和 state 发生变化时,React 会根据变化后的 props 和 state 创建一个新的 virtual DOM,然后比较新旧两个 vritual DOM 是否一致,只有当两者不同时,React 才会将 virtual DOM 渲染真实的 DOM 结点,而对 React 进行性能优化的核心就是减少渲染真实 DOM 结点的频率,间接地指出开发者应该准确判断 props 和 state 是否真正发生了变化。
什么是
Immutable Data
Immutable Data 顾名思义就是一旦创建就不能再被更改的数据。在js中实现数据不可变,有两个方法:
const(es6)
Object.freeze(es5)
但是这两种方法都是shallow处理,遇到嵌套深的结构就需要递归处理,深度拷贝的坏处很明显,即对象越复杂,性能开销越大。在JavaScript中,对象默认是可变的。当你复制一个对象时,JavaScript不得不复制每一个属性来保证这两个对象相互独立。当数据量及其庞大的时候,这种性能的瓶颈就显而易见了。
Immutable data
及其原理Immutable 实现的原理是
Persistent Data Structure
(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。1.
structural sharing
结构共享当我们对一个
Immutable
对象进行操作的时候,ImmutableJS基于哈希映射树(hash map tries)和vector map tries,只clone该节点以及它的祖先节点,其他保持不变,这样可以共享相同的部分,大大提高性能。在React.js中使用
Immutable Data
PureRenderMixin
当我们说一个
React component
是pure render
,是指它的render function
是pure function
。 Pure render 的好处之一就是可以在shouldComponentUpdate
中做性能优化。最常見的做法就是用 shallow equal 检查 props 和 state 有无改变,有改变才update component
。而React 中自带的
PureRenderMixin
也只是简单的浅比较,不能用于深层比较:Immutable 可以给 React 应用带来数十倍的性能提升,数据的不可变性使得追踪变化的开销变小,当state更新时,如果数据没变,React也会去做
virtual dom
的diff,这就产生了浪费。shouldComponentUpdate
当一个 React 组件的 props 和 state 发生变化时,React 会根据变化后的 props 和 state 创建一个新的 virtual DOM,然后比较新旧两个 vritual DOM 是否一致,只有当两者不同时,React 才会将 virtual DOM 渲染真实的 DOM 结点,而对 React 进行性能优化的核心就是减少渲染真实 DOM 结点的频率,间接地指出开发者应该准确判断 props 和 state 是否真正发生了变化。然而,
shouldComponentUpdate
也只能进行shadow compare,当比较的值是数组或者对象时,这种方式就不work了,如果数据是 Immutable Data 的话,那么数据发生变化就会生成新的对象,开发者只需要检查对象应用是否发生变化即可。
Immutable 则提供了简洁高效的判断数据是否变化的方法,只需 === 和 is 比较就能知道是否需要执行 render(),而这个操作几乎 0 成本,所以可以极大提高性能。
函数式编程
Immutable 本身就是函数式编程中的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入一致,输出必然一致,这样开发的组件更易于调试和组装。通常对于非常简单的组件,我们通常可以使用函数组件:
但是函数组件也是一个 React 组件,当使用时,也会在内部调用
componentWillMount
、componentDidMount
、componentWillUnmount
等生命周期函数。为了提高性能,我们可以将其作为函数调用,而不是React组件调用。
改成函数调用后,没有生成
React.createElement
,也就没有了 React 组件的生命周期函数。函数式编程的几大概念:
1.函数是一等公民 2.数据是不可变的 3.强制使用纯函数(没有任何副作用,输出完全由输入决定 4.函数只接受一个参数(科里化 5.函数 无状态
Immutable 可以让代码更容易维护,在js操作数组和对象的原生方法中,很容易违反这种原则,例如:
数组中会改变原数组的方法有:
也不要直接去修改一个对象的字段:
函数只接受一个参数,也就是函数的科里化,例如在Redux中middleware的实现:
Immutable API
对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
Immutable.fromJS
可以将普通的js对象深层次的转化为Immutable
对象 (Object=>Map,Array=>List)Immutable.Map
只能浅层次的转化为immutable对象map2包含了更新后的数据,而map1数据依然保持不变。任何数据的修改都不影响最原始的数据,在让我们在引用数据的时候毫无后顾之忧
有序索引集,类似于 JavaScript 中的 Array
无序列表,且不能重复。类似于ES6的Set
与
Object.is()
类似,都是对值的比较实例
React推荐将初始state设为Immutable: