简述
Facebook 工程师 Lee Byron 花费 3 年时间打造,immutable.js是由facebook开源的一个项目,主要是为了解决javascript Immutable Data的问题。它内部实现了一套完整的 Persistent Data Structure,还有很多易用的数据类型。像 Collection、List、Map、Set、Record、Seq。有非常全面的map、filter、groupBy、reduce“find函数式操作方法。同时 API 也尽量与 Object 或 Array 类似。
其中有 3 种最重要的数据结构说明一下:
Map:键值对集合,对应于 Object,ES6 也有专门的 Map 对象
List:有序可重复的列表,对应于 Array
Set:无序且不可重复的列表
1.fromJS()
将 JavaScript Object 和 Array 深度转换为 Immutable Map 和 List
语法:
fromJS(json: any, reviver?: (k: any, v: Iterable<any, any>) => any): any
fromJS() 的使用方式类似于 JSON.parse(),接收两个参数:json 数据和 reviver 函数。reviver 为一个可选参数。
注意:
JS object转换成Immutable Maps时, JS对象的属性永远都是字符串
var obj = {1: "one"};
var map = Map(obj);
map.get("1"); // "one"
map.get(1); // undefined
2. List
List为immutable数据类型, 是有序索引密集的集合,和JS中的Array相似。除List()构造方法外,List拥有两个静态方法:List.isList() 和List.of()。
class List<T> extends Collection.Indexed<T>
List() 是一个构造方法,可以用于创建新的 List 数据类型。该构造方法接收的参数类型如下:
List<T>(): List<T> List<T>(iter: Iterable.Indexed<T>): List<T> List<T>(iter: Iterable.Set<T>): List<T> List<K, V>(iter: Iterable.Keyed<K, V>): List<any> List<T>(array: Array<T>): List<T> List<T>(iterator: Iterator<T>): List<T> List<T>(iterable: Object): List<T>
List.isList()用来判断是否为一个List集合,即是否为List类型
List.isList(maybeList: any): boolean
List.of()用来创建一个新的List,并且包含values
List.of<T>(...values: T[]): List<T>
// 1. 查看 List 长度
const $arr1 = List([1, 2, 3]);
$arr1.size
// => 3
// 2. 添加或替换 List 实例中的元素
// set(index: number, value: T)
// 将 index 位置的元素替换为 value,即使索引越界也是安全的
const $arr2 = $arr1.set(-1, 0);
// => [1, 2, 0]
const $arr3 = $arr1.set(4, 0);
// => [ 1, 2, 3, undefined, 0 ]
// 3. 删除 List 实例中的元素
// delete(index: number)
// 删除 index 位置的元素
const $arr4 = $arr1.delete(1);
// => [ 1, 3 ]
// 4. 向 List 插入元素
// insert(index: number, value: T)
// 向 index 位置插入 value
const $arr5 = $arr1.insert(1, 1.5);
// => [ 1, 1.5, 2, 3 ]
// 5. 清空 List
// clear()
const $arr6 = $arr1.clear();
// => []
3. Map
Map 可以使用任何类型的数据作为 Key 值,并使用 Immutable.is() 方法来比较两个 Key 值是否相等。Map集合和List集合的静态方法基本相似,Map() 是 Map 类型的构造方法,行为类似于 List(),用于创建新的 Map 实例,此外,还包含两个静态方法:Map.isMap() 和 Map.of()。这个是针对对象而言。
// 1. Map 实例的大小
const $map1 = Map({ a: 1 });
$map1.size
// => 1
// 2. 添加或替换 Map 实例中的元素
// set(key: K, value: V)
const $map2 = $map1.set('a', 2);
// => Map { "a": 2 }
// 3. 删除元素
// delete(key: K)
const $map3 = $map1.delete('a');
// => Map {}
// 4. 清空 Map 实例
const $map4 = $map1.clear();
// => Map {}
// 5. 更新 Map 元素
// update(updater: (value: Map<K, V>) => Map<K, V>)
// update(key: K, updater: (value: V) => V)
// update(key: K, notSetValue: V, updater: (value: V) => V)
const $map5 = $map1.update('a', () => (2))
// => Map { "a": 2 }
// 6. 合并 Map 实例
const $map6 = Map({ b: 2 });
$map1.merge($map6);
// => Map { "a": 1, "b": 2 }
OrderedMap 是 Map 的变体,它除了具有 Map 的特性外,还具有顺序性,当开发者遍历 OrderedMap 的实例时,遍历顺序为该实例中元素的声明、添加顺序。
4. Set
Set 和 ES6 中的 Set 类似,都是没有重复值的集合。
// 1. 创建 Set 实例
const $set1 = Set([1, 2, 3]);
// => Set { 1, 2, 3 }
// 2. 添加元素
const $set2 = $set1.add(1).add(4);
// => Set { 1, 2, 3, 4 }
// 3. 删除元素
const $set3 = $set1.delete(3);
// => Set { 1, 2 }
// 4. 并集
const $set4 = Set([2, 3, 4, 5, 6]);
$set1.union($set1);
// => Set { 1, 2, 3, 4, 5, 6 }
// 5. 交集
$set1.intersect($set4);
// => Set { 3, 2 }
// 6. 差集
$set1.subtract($set4);
// => Set { 1 }
OrderedSet 是 Set 的遍历,可以保证遍历的顺序性。用法类似于OrderedMap。
5. Stack
Stack 是基于 Signle-Linked List 实现的可索引集合,使用 unshift(v) 和 shift() 执行添加和删除元素的复杂度为 O(1)。
// 1. 创建 Stack 实例
const $stack1 = Stack([1, 2, 3]);
// => Stack [ 1, 2, 3 ]
// 2. 取第一个元素
$stack1.peek()
// => 1
// 2. 取任意位置元素
$stack1.get(2)
// => 3
// 3. 判断是否存在
$stack1.has(10)
// => false
6.Range() 和 Repeat()
Range(start?, end?, step?) 接收三个可选参数,返回一个 Seq 集合。从 start (inclusive, 默认是0) 到 end (exclusive, 默认是infinity), by step(默认值是1).当 start === end 时,返回一个空的range
// 1. 不传参
Range();
// => Range [ 0...Infinity ]
// 2. 设置 start 起点
Range(10);
// => Range [ 10...Infinity ]
// 3. 设置 start 起点和 end 终点
Range(10, 20);
// => Range [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
// 4. 设置 start 起点、end 终点和 step 步长
Range(10, 20, 3);
// => Range [ 10, 13, 16, 19 ]
Repeat(value, times?) 接收两个参数,其中 times 重复次数是可选参数:
Repeat('foo');
// => Repeat [ foo Infinity times ]
Repeat('foo', 3);
// => Repeat [ foo 3 times ]
类似 Range() 和 Repeat(value) 这样生成无限长度集合的操作,内部都存在惰性计算的机制,只有真实取值时才会生成相应的结果。
7.Iterable 和 Collection
Iterable 是键值对形式的集合,其实例可以执行遍历操作,是 immutable.js 中其他数据类型的基类,所有扩展自 Iterable 的数据类型都可以使用 Iterable 所声明的方法,比如 map 和 filter 等。
Collection 是 Concrete Data Structure 的基类,使用该类时需要至少继承其子类中的一个:Collection.Keyed / Collection.Indexed / Collection.Set。
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: http://www.w3cplus.com/javascript/immutable-js.html © w3cplus.com