初步阅读 Immutable.js官网文档, 作出如下记录,以便查阅。
1.fromJS()
深度的将数组转换成Immutable Lists,将对象转换成Immutable Maps。
语法:
fromJS(json: any, reviver?: (k: any, v: Iterable<any, any>) => any): any
reviver 为一个可选参数
示例:
Immutable.fromJS({
a: {
b: [1, 2, 3],
c: 40
}
});
// 得到
Map {
"a": Map {
"b": List [1, 2, 3],
"c": 40
}
}
值得注意的是,将JS object转换成Immutable Maps时, JS对象的属性永远都是字符串,即使写为没有字符串的简写形式
var obj = {1: "one"};
var map = Map(obj);
map.get("1"); // "one"
map.get(1); // undefined
2.is()
用于检测值的相等性,注意这和Object.is()的区别
语法:
is(first: any, second: any): boolean
示例:
var map1 = Immutable.Map({a: 1, b: 1});
var map2 = Immutable.Map({a: 1, b: 1});
map1 !== map2; // true
Object.is(map1, map2); // false
Immutable.is(map1, map2); // true 只检测值是否相等
另外注意这个差别:
Immutable.is(0, -0); // true
Object.is(0, -0); // false
List
List是有序索引密集的集合,和JS中的Array很像
定义:
class List<T> extends Collection.Indexed<T>
1.静态方法
1.List.isList()
判断一个集合是否为一个List集合
List.isList(maybeList: any): boolean
示例:
const plainArr = [1, 2, 3];
const listFromPlainArray = List(plainArr);
List.isList(listFromPlainArray); // true
listFromPlainArray.toJS(); // [1, 2, 3]
2.List.of()
创建一个新的List,并且包含values
List.of<T>(...values: T[]): List<T>
实例:
List.of(1, 2, 3, 4);
var myList = List.of({x: 1}, 2, [3]);
myList.toJS(); // [ {x: 1}, 2, [3] ]
1.Deep persistent changes
setIn()
在keyPath的地方设置新的value,如果对应的keyPath中不存在keys,则返回一个新的immutable Map
语法:
setIn(keyPath: Array<any>, value: any): List<T>
setIn(keyPath: Iterable<any, any>, value: any): List<T>
// setIn([index(, otherIndex)], value)
表示对应的索引位置设置值
示例:
Immutable.fromJS([0, 1, 3, [5, 7]]).setIn([3, 2], 9).toJS(); // [0, 1, 3, [5, 7, 9]]
2.creating subsets
rest()
返回一个新的可循环的实体,除了第1个
var myList = List.of(1, 2, 3);
myList.rest().toJS(); // [2, 3]
butLast()
和上面的正好相反,除去最后一个
myList.butLast().toJS(); // [1, 2]
skip()
跳过的数量
myList.skip(2).toJS(); // [3]
skipWhile()
从 predicate函数开始返回 false时后面的实体
语法:
skipWhile(
predicate: (value: T, key: number, iter: Iterable<number, T>) => boolean,
context?: any
): Iterable<number, T>
示例:
Seq.of('dog', 'frog', 'cat', 'hat', 'god')
.skipWhile(x => x.match(/g/));
// 到 'cat'时返回false, 所以返回
// Seq [ 'cat', 'hat', 'god']
skipUntil()
从 predicate函数开始返回 true时后面的实体
实例:
Seq.of('dog', 'frog', 'cat', 'hat', 'god')
.skipUntil(x => x.match(/hat/))
// Seq ['hat', 'god']
zip()
使用默认的 zipper
函数对2个集合进行处理
var a = Seq.of(1, 2, 3, 4, 5);
var b = Seq.of('a', 'b', 'c');
var c = a.zip(b);
// Seq [ [1, 'a'], [2, 'b'], [3, 'c'] ]
// 多的部分省略掉了
zipWith()
和上面不同的时,这个可以自定义 zipper 函数, 按照自己的逻辑进行处理集合
var a = Seq.of(1, 2, 3);
var b = Seq.of(4, 5, 6);
// (x, y) => x + y 表示的是zipper函数
// b 表示的是第2个集合
var c = a.zipWith((x, y) => x + y, b);
// Seq [5, 7, 9]
Map
Map集合和List集合的静态方法基本相似,Map.isMap()
| Map.of()
,这个是针对对象而言
update()
如果存在相应的key,则通过 updater 对其进行更新,并返回更新后的新的Map;如果没有定义key,则更新的为Map自身
3种语法:
update(updater: (value: Map<K, V>) => Map<K, V>): Map<K, V>
update(key: K, updater: (value: V) => V): Map<K, V>
update(key: K, notSetValue: V, updater: (value: V) => V): Map(K, V)
示例:
#1 不设置key,对整个Map集合进行更新
// 相当于 map.set(key, updater(map.get(key, notSetValue)))
const originalMap = Immutable.Map({
key: 'value',
subObject: { subKey: 'subValue' }
});
const newMap = originalMap.update(map => {
return Immutable.Map(map.get('subObject'))
});
newMap.toJS(); // { subKey: 'subValue'}
#2 对存在的key进行更新
const newMap = originalMap.update('key', value => value + value);
newMap.toJS();
// {
key: 'valuevalue',
subObject: { subkey: 'subValue'}
}
#3 对不存在的key,进行更新
var originalMap = Immutable.Map({
key: 'value'
});
var newMap = originalMap.update('noKey', 'noValue', value => value + value);
newMap.toJS();
// {
key: 'value',
noKey: 'no valueno value'
}
mergeDeep
当2个集合产生了冲突, 将递归合并嵌套的数据
示例:
var x = Immutable.fromJS({
a: { x: 10, y: 10 },
b: { x: 20, y: 50 }
});
var y = Immutable.fromJS({
a: { x: 2 },
b: { y: 5 },
c: { z: 3 }
});
x.mergeDeep(y);
// 结果
Map {
a: { x: 2, y: 10 },
b: { x:20, y: 5 },
c: { z: 3 }
}
setIn()
根据 keyPath 来设置 value, 如果对应的 keyPath不存在,则创建新的 key
示例:
#1 'keyPath' 存在的情况
const originalMap = Immutable.fromJS({
subObject: {
subKey: 'subValue',
subSubObject: {
subSubKey: 'subSubValue'
}
}
});
const newMap = originalMap.set(['subObject', 'subSubObject', 'subSubKey'], 'great');
newMap.toJS();
subObject: {
subKey: 'subValue',
subSubObject: {
subSubKey: 'great'
}
}
#2 'keyMap'不存在的情况
var map = Immutable.fromJS({
a: 'hello',
b: {
x: 12,
y: 34
}
});
var newMap = map.setIn(
['b', 'z'],
50
);
newMap.toJS();
{
a: 'hello',
b: {
x: 12,
y: 34,
z: 50
}
}
Transient changes
1.withMutation
如果想应用一系列可变操作产生一个新的immutable Map,可以使用 withMutation
来产生一个中间可变Map。只有 set ,merge 方法能用在中间可变的集合中
示例:
var map1 = Immutable.Map();
var map2 = map1.withMutation(map => {
map.set('a', 1).set('b', 2).set('c', 3)
});
map2.toJS();
{
a: 1,
b: 2,
c: 3
}
Range()
返回一个 Seq 集合, 从 start
(inclusive, 默认是0) 到 end
(exclusive, 默认是infinity), by step
(默认值是1).当 start === end 时,返回一个空的range
语法:
Range(start?: number, end?: number, step?: number): Seq.Indexed<number>
示例:
Range(); // Seq [0, 1, 2....]
Range(10, 15); // Seq [10, 11, 12, 13, 14]
Range(10, 30, 5); // Seq [10, 15, 20, 25]
Range(30, 10, 5); // Seq [30, 25, 20, 15]
Range(30, 30); Seq []
Iterable
Iterable 是一系列能够迭代的键值对,是immutable.js中所有集合的基类,从而使得所有的集合都拥有可迭代的方法(比如map, filter)
class Iterable<K, V>
静态方法
Iterable.isIterable()
示例:
var Iterable = Immutable.Iterable;
Iterable.isIterable([]); // false
Iterable.isIterable({}); // false
Iterable.isIterable(Immutable.Map()); // ture
Iterable.isIterable(Immutable.List()); // ture
Iterable.isIterable(Immutable.Seq()); // ture
Iterable.isIterable(Immutable.Stack()); // ture
Collection
Collection对实体数据结构是个抽象基类,不能够直接的构建
class Collection<K, V> extends Iterable<K, V>
总结
immutable.js 对于数据的操作都是同个集合的方式来完成。对于数据无非就是增删改查, immutable.js最大的优点就是不会改变原有的数据,都是通过返回新的集合类型来完成的。另外提供了大量的方法来操作数据。
比较最要的集合有List, Map。然后就是几种方法,比如对于集合和常规的JS对象数组的转换,会使用到 Immutable.fromJS()
| Immutable.toJS()
。