一. 基本概念
immutable 是 Facebook 开源的一个项目,用于实现 javascript 的不可变数据(修改对象属性会返回一个新的对象,基于结构共享,而不是对象deepClone),解决引用带来的副作用(好多地方引用了同一个对象,某一处改变了对象的属性值导致了某些不可预测的问题发生)。
二. 常用数据类型
- List: 有序索引集,类似JavaScript中的Array。
- Map: 无序索引集,类似JavaScript中的Object。
- OrderedMap: 有序的Map,根据数据的set()进行排序。
- Set: 没有重复值的集合。
- OrderedSet: 有序的Set,根据数据的add进行排序。
- Stack: 有序集合,支持使用unshift()和shift()添加和删除。
- Record: 一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。
- Seq: 序列,但是可能不能由具体的数据结构支持。
- Collection: 是构建所有数据结构的基类,不可以直接构建。
三. 常用API
原生js转换为immutableData
Immutable.fromJS([1,2]) // immutable的 list
Immutable.fromJS({a: 1}) // immutable的 map
从immutableData 回到 JavaScript 对象
immutableData.toJS()
判断两个immutable数据是否一致
Immutable.is(immutableA, immutableB)
判断是不是map或List
Immutable.Map.isMap(x)
Immutable.Map.isList(x)
对象合并(注意是同个类型)
immutableMaB = immutableMapA.merge(immutableMaC)
Map的增删查改
查
immutableData.get('a') // {a:1} 得到1。
immutableData.getIn(['a', 'b']) // {a:{b:2}} 得到2。访问深层次的key
增和改(注意不会改变原来的值,返回新的值)
immutableData.set('a', 2) // {a:1} 得到1。
immutableData.setIn(['a', 'b'], 3)
immutableData.update('a',function(x){return x+1})
immutableData.updateIn(['a', 'b'],function(x){return x+1})
删
immutableData.delete('a')
immutableData.deleteIn(['a', 'b'])
List的增删查改
如同Map,不过参数变为数字索引。
比如immutableList.set(1, 2)
其它便捷函数
如同underscore的方法
四. List
// utils.js
function print(obj) {
console.log(obj)
}
function printJS(obj) {
console.log(obj.toJS());
}
function writeText(msg) {
document.body.appendChild(document.createTextNode(msg));
}
一些简单的使用例子
const {List, is} = Immutable;
const l1 = List.of(1, 2, 3, 4, 5);
l1.forEach(v => console.log(v));
console.log(List.isList(l1));
const l2 = new List([6, 7, 8, 9, 10]);
printJS(l2);
print(l2.count())
print(`l2有大于8的元素个数为: ${l2.countBy(v => v > 8).toJS().true}`);
const l3 = l2.delete(0);
printJS(l3);
const l4 = List.of([1, 2, 3], [4, 5, 6])
const l5 = l4.deleteIn([0, 1]).deleteIn([1, 2]);
printJS(l5);
print(l5.getIn([1, 0]));
for (const key of l5.keys()) {
print(l5.get(key))
}
const l6 = l5.clear();
printJS(l6);
const l7 = l6.concat([1,2,3]);
printJS(l7);
print(l7.entries());
for(const [key, value] of l7.entries()){
print(`key: ${key} value: ${value}`);
}
const l8 = new List([1,2,3]);
const l9 = new List([1,2,3]);
print(is(l8, l9))
print(l8.equals(l9))
print(l8.every(v => v > 0))
print(l8.max())
const l10 = Immutable.mergeDeep(l8, l9);
printJS(l10);
printJS(l10.pop())
print(l10.push(3).size);
print('累加器结果: ' + l10.reduce((total, current) => total + current, 0))
const l11 = new List([1,2,3]);
printJS(l11.takeLast(2))
五. Map
const {Map} = Immutable;
const m1 = new Map({
name: 'david',
age: 27,
hobby: 'programming'
});
printJS(m1)
print(m1.get('name'))
const m2 = m1.butLast();
printJS(m2)
print(m2.count())
printJS(m1.countBy(value => {
return value !== 'david'
}))
const m3 = m1.deleteIn(['name'])
printJS(m3)
for(const [key, value] of m1.entries()){
print(`key: ${key}, value: ${value}`)
}
const m4 = m1.filter(v => v.length > 3);
printJS(m4)
const [key, value] = m1.findEntry(v => v.length > 3);
print(`${key}-${value}`)
m1.forEach((value, key, map) => {
print(`${key}: ${value}`)
})
print([...m1.keys()])
const m5 = new Map([
["level", "xiaobai"]
]);
printJS(m5)
const m6 = m1.merge(m5);
printJS(m6)
print(m6.get("level"))
const m7 = m6.set("level", "dashen")
printJS(m7)
print([...m7.values()])
const m8 = m1.merge(new Map({
skillLevel: {
css: "good",
javascript: "familar",
html: "familar"
}
}))
printJS(m8)
const m9 = m8.setIn(["skillLevel", "css"], "excellent")
print(`css的掌握水平为: ${m9.getIn(["skillLevel", "css"])}`)
六. OrderedMap
这种Map类型能够保证迭代时候属性的顺序与设置时候的顺序相同
该数据类型的API与Map相同
const {OrderedMap: Map} = Immutable;
const m1 = new Map({
name: "david",
age: 27,
hobby: "programming"
});
writeText(m1.get("name"))
// 下面遍历一下看看顺序
m1.forEach((value, key) => {
print(`${key} ${value}`);
});
for(const [key, value] of m1.entries()){
print(`${key}-${value}`)
}
七. Set
没有重复值, 可以用该数据结构进行去重
const { Set } = Immutable;
const s1 = new Set([1,1,2,2,3,4,5]);
writeJS(s1);
const s2 = s1.add(6);
writeJS(s2);
const s3 = s2.butLast();
writeJS(s3);
writeText(s3.count());
writeText(s3.has(5));
const s4 = s1.delete(1)
writeJS(s4)
writeText(s4.toArray())
八. OrderedSet
OrderedSet是按照添加顺序作为元素迭代顺序的Set, API同Set
九. Stack
栈结构没支持shift和unshift
const { Stack } = Immutable;
const s1 = Stack.of([1,2,3,4,5])
writeJS(s1)
const s2 = s1.push(6).push(7);
writeJS(s2)
const s3 = s2.unshift(8);
writeJS(s3)
const s4 = s3.pop();
writeJS(s4)
writeText(s4.get(0))
const s5 = s4.shift();
writeJS(s5)
十. Record
一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。
var ABRecord = Immutable.Record({a:1, b:2})
const r1 = new ABRecord({
b: 3
});
writeJS(r1)
writeText(r1.get("a"))
writeText(r1.get("b"));
const r2 = r1.remove("b");
writeJS(r2);
十一. Seq
操作序列, 串行化的一系列数据处理逻辑, 最后能够使用toList, toMap,toSet等函数转化为对应的数据类型
var oddSquares = Immutable.Seq([1,2,3,4,5,6,7,8]).filter(x => x % 2).map(x => x * x);
writeJS(oddSquares)
// flip为key-value调换位置, 再次就换回来了
var obj = Immutable.Seq({a: 1, b: 1, c: 1}).flip().map(key => key.toUpperCase()).flip().toObject();
writeJS(obj, false)
writeJS(Immutable.Seq([1,2,3,4,5]).reverse().toSet())