1. 什么是 Immutable ?
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。主要原理是采用了 Persistent Data Structure(持久化数据结构),就是当每次修改后我们都会得到一个新的版本,且旧版本可以完好保留,也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),就是对于本次操作没有修改的部分,我们可以直接把相应的旧的节点拷贝过去,这其实就是结构共享。
2. Immutable 有什么优点?
2.1 降低复杂度,避免副作用
在 Javascript 中,对象都是引用类型,在按引用传递数据的场景中,会存在多个变量指向同一个内存地址的情况,这样会引发不可控的副作用,如下代码所示:
let obj1 = { name: '张三' };
let obj2 = obj1;
obj2.name = '李四';
console.log(obj1.name); // 李四
使用 Immutable 后:
import { Map } from 'immutable';
let obj1 = Map({ name: '张三'});
let obj2 = obj1;
obj2.set({name:'李四'});
console.log(obj1.get('name')); // 张三
当我们使用 Immutable 降低了 Javascript 对象 带来的复杂度的问题,使我们状态变成可预测的。
2.2 节省内存
Immutable 采用了结构共享机制,所以会尽量复用内存。
import { Map } from 'immutable';
let obj1 = Map({
name: 'zcy',
filter: Map({age:6})
});
let obj2 = obj1.set('name','zcygov');
console.log(obj1.get('filter') === obj2.get('filter')); // true
// 上面 obj1 和 obj2 共享了没有变化的 filter 属性
2.3 方便回溯
Immutable 每次修改都会创建一个新对象,且对象不变,那么变更的记录就能够被保存下来,应用的状态变得可控、可追溯,方便撤销和重做功能的实现,请看下面代码示例:
import { Map } from 'immutable';
let historyIndex = 0;
let history = [Map({ name: 'zcy' })];
function operation(fn) {
history = history.slice(0, historyIndex + 1);
let newVersion = fn(history[historyIndex]);
// 将新版本追加到历史列表中
history.push(newVersion);
// 记录索引,historyIndex 决定我们是否有撤销和重做
historyIndex++;
}
function changeHeight(height) {