Immutable学习笔记

来源:互联网 发布:mysql limit与where 编辑:程序博客网 时间:2024/06/07 17:06

Immutable学习笔记(整合了相关博客的内容)

[TOC]
我们在使用react的redux的时候,我们要求所有state只能由一个store存储,然后每一次修改state,都需要返回一个新的state,以上是我们的需求。而Immutable就正好迎合了我们的这部分需求。
以往我们都是用类似下面的代码来重新拼接返回一个新的state

return Object.assign({},state, {    todos: [          ...state.todos,          {            text: action.text,            completed: false          }     ]})

现在我们大可使用Immutable来解决这个问题。

什么是 Immutable Data

Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。请看下面动画:

Immutable节点共享

Immutable的优点

  • 使得数据可以被回溯,由于每次更改都不改变原数据,类似撤回等功能很容就可以实现
  • 节省内存,Immutable.js 使用了 Structure Sharing 会尽量复用内存,甚至以前使用的对象也可以再次被复用。没有被引用的对象会被垃圾回收。
  • Immutable 本身就是函数式编程中的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入一致,输出必然一致,这样开发的组件更易于调试和组装。

Immutable使用

两个Immutable对象的比较

用is()或者equal(),这是进行值比较

let map1 = Map({a:1, b:1, c:1});let map2 = Map({a:1, b:1, c:1});console.log(map1 === map2); //falseconsole.log(map1.equals(map2)); //trueconsole.log(is(map1, map2)); //true

Immutable.is 比较的是两个对象的 hashCode 或 valueOf(对于 JavaScript 对象)。由于 immutable 内部使用了 Trie 数据结构来存储,只要两个对象的 hashCode 相等,值就是一样的。这样的算法避免了深度遍历比较,性能非常好。

cursor

由于 Immutable 数据一般嵌套非常深,为了便于访问深层数据,Cursor 提供了可以直接访问这个深层数据的引用。

import Immutable from 'immutable';import Cursor from 'immutable/contrib/cursor';let data = Immutable.fromJS({ a: { b: { c: 1 } } });// 让 cursor 指向 { c: 1 }let cursor = Cursor.from(data, ['a', 'b'], newData => {  // 当 cursor 或其子 cursor 执行 update 时调用  console.log(newData);});cursor.get('c'); // 1cursor = cursor.update('c', x => x + 1);cursor.get('c'); // 2

Map,List,fromJs,Seq区别

  • Map()接收的是Object
  • List()接收的是Array
  • fromJs接收的是Object或者Array
  • Seq接收Object或者Array

这里主要说Seq:
Seq 是不可变的 — 一旦 Seq 创建便不能修改, 添加, 排列或其它修改. 任何修改操作都会生成一个新的 Seq.
Seq 是惰性的 — Seq 尽可能少的去相应函数调用。

var oddSquares = Seq.of(1,2,3,4,5,6,7,8)    .filter(x => { console.log("$", x); return x % 2}).map(x => {console.log("#"); return x * x});console.log(oddSquares.get(1));/*---输出---*/// $ 1// $ 2// $ 3// #// 9//此处的filter执行了3次,map执行了1次,后续的不执行

然后所有的集合都可以用toSeq()转成Seq

批量修改

由于每一次修改都会生成一个新的immutable对象有一定的性能损耗,可以使用withMutations方法,使批量修复在临时集合拷贝上发生。

var list1 = List.of(1,2,3);var list2 = list1.withMutations(function (list) {    list.push(4).push(5).push(6);});console.log(list1.size === 3);console.log(list2.size === 6);

注: immutable 还提供了 asMutable 和 asImmutable , 但是只有在 withMutation 不能满足情况的时候使用。注意不要返回一个可变的拷贝,会导致非预知的行为。

重要!:只有特殊的几个方法能使用 withMutation 其中包括 set, pushpop。这些方法能直接作用于内部数据结构,而方法如 map, filter, sort, splice 一定不会修改可修改集合并返回新的不变集合。

List

构建List,可用List(Array) or List.of(Values)

参考资料:
深入浅出 - Redux
Immutable 详解及 React 中实践

0 0
原创粉丝点击