Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。请看下面动画:
优点: ✌
-
降低了Mutable带来的复杂度
-
节省内存空间
-
拥抱函数式变成
-
方便开发Undo/Redo, Copy/Paste 缺点: 😒
-
容易与原生对象 Immutable.js 的几种数据类型:
-
List:有序索引集,类似JavaScript中的Array。 -
Map:无序索引集,类似JavaScript中的Object。 -
OrderedMap:有序的Map,根据数据的set()进行排序。 -
Set:没有重复值的集合。 -
OrderedSet:有序的Set,根据数据的add进行排序。 -
Stack:有序集合,支持使用unshift()和shift()添加和删除。 -
Record:一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。 -
Seq:序列,但是可能不能由具体的数据结构支持。 -
Collection:是构建所有数据结构的基类,不可以直接构建。
用的最多的就是List、Map以及Set,所以我们主要介绍这三个数据类型的API: 🙌
一、 List
List列表是有序索引的秘密集合,很像Javascript数组。
1.创建List
注意: List是工厂方法,不能使用new初始化
const list1 = List([1, 2, 3, 4])
console.log(list1)
2. isList
判断是否是List ,返回一个布尔值
console.log(List.isList(list1)) //true
console.log(List.isList([1,2,3])) //false
3. List.of()
创建一个包含的新列表
const list2 = List.of(1,2,3,4)
console.log(list2)
4. size取得list的长度
console.log(list1.size) //4
5. set
set方法用来设定指定的下表的值 set(下表, 值), 如果index已经存在于此列表中,它将被替换。
const list3 = list1.set(2,666) //[1, 2, 666, 4]
console.log(list1.toJS())
console.log(list3.toJS())
index可能是一个负数,从列表末尾开始索引。v.set(-1, "value")设置列表中的最后一个项目。
const list4 = list1.set(-1,-111)
console.log(list4.toJS()) //[1, 2, 3, -111]
如果index大于size。
const list5 = list1.set(10, 1000);
console.log(list5.toJS())
//[1, 2, 3, 4, undefined, undefined, undefined, undefined, undefined, undefined, 1000]
6.delete
删除指定下标值 delete(下标)
const list6 = list1.delete(2);
console.log(list6.toJS())
index可能是一个负数,从列表末尾开始索引。v.delete(-1)删除列表中的最后一个项目。
const list2 = list1.delete(-1);
console.log(list2.toJS()) //[1,2,3]
7. insert
插入值 insert(下标, 值)
const list8 = list1.insert(2,'jd.com');
console.log(list8.toJS()) //[1, 2, "jd.com", 3, 4]
下标是负数(从右往左数)
const list7 = list1.insert(-3,'qq.com');
console.log(list7.toJS()) //[1, 2, "qq.com", 3, 4]
8. update
用来更新指定下标的值(下标, callback)
const list8 = list1.update(1, x => x*100);
console.log(list8.toJS()) //[1, 200, 3, 4]
9. setIn
「用来设置指定下标的值」 如果下标小于size,则替换值
const list1 = iList([ 0, 1, 2, List([ 3, 4 ])])
const list2 = list1.setIn([3, 0], 999);
console.log(list2) //List [ 0, 1, 2, List [ 999, 4 ] ]
如果下标大于size,则插入值
const list1 = iList([ 0, 1, 2, List([ 3, 4 ])])
const list2 = list1.setIn([3, 3], 999);
console.log(list2.toJS()) //List [ 0, 1, 2, List [[3, 4, undefined, 999] ]
10. clear
清空并返回一个长度为0的新数组
const list10 = list1.clear();
console.log(list10.toJS()) //[]
11. setSize
重新设定数组长度,小于原数组会截断,大于原数组会用undifined进行填充
const list11 = list1.setSize(6);
console.log(list11.toJS()) //[1, 2, 3, 4, undefined, undefined]
12. setIn()用来定义嵌套结构的值
同理还有deleteIn、updateIn、insertIn
const arr1 = List([
List([1,2,3]),
List([11,22,33]),
List([111,222,333])
])
const arr2 = arr1.setIn([1,1],999); //下标为(1,1)的元素变为999console.log(arr2.toJS())
13. concat 连接List
merge是concat的别名。
const list2 = List([11,22,33]);
const list3 = List([44,55,66]);
const list4 = List([77,88,99]);
const list5 = list1.concat(list2, list3, list4);
console.log(list5.toJS()) //[1,2,3,4,11,22,33,44,55,66,77,88,99]
14. flatter扁平化List
List.flatten(value) value可以是数值(数值是几,表示拉平几层,Infinity表示所有都拉平), 也可以写true或者false
true代表浅拉平,只拉平第一层
const arr1 = List([
List([
1,
2,
List([
'aa',
'bb',
List([
'cccc',
'ddddd'])
])
]),
List([11,22,33]),
List([111,222,333])
])
const arr2 = arr1.flatten(true);console.log(arr2.toJS())
false代表深拉平,所有的都扁平化。
const arr1 = List([
List([
1,
2,
List([
'aa',
'bb',
List([
'cccc',
'ddddd'
])
])
]),
List([11,22,33]),
List([111,222,333])
])
const arr2 = arr1.flatten(false);console.log(arr2.toJS())
//[1, 2, "aa", "bb", "cccc", "ddddd", 11, 22, 33, 111, 222, 333]
15. find
find查找,返回第一个符合的结果,如果没找到,则返回undefined
const arr1 = List(['张三','Iric','Lisa','王麻子']);
const res = arr1.find(item => item === 'Lisa');
console.log(res) //Lisa
const res2 = arr1.find(item => item === 'Lisaa');
console.log(res2) //undefined
16. findLast
find查找,返回最后一个符合的结果,没找到返回undefined
const arr1 = List(['张三','Iric','Lisa','王麻子','张晨']);
const res = arr1.findLast(item => item.includes('张'));
console.log(res) //张晨
17. keys
返回所有下标
const arr1 = List(['张三','Iric','Lisa','王麻子','张晨']);
const keys = arr1.keys();
for(const key of keys){
console.log('k',key)
}
18. values
返回所有值
const arr1 = List(['张三','Iric','Lisa','王麻子','张晨']);
const values = arr1.values();
for(const value of values){
console.log('values',value)
}
19. entries
返回所有entry,(key, value)形式。
const arr1 = List(['张三','Iric','Lisa','王麻子','张晨']);
const entries = arr1.entries();
for(const entry of entries){
console.log('entries',entry)
}
20. groupBy
分组
const people = List([
Map({
name:'Lisa',
sex:'man'
}),
Map({
name:'Jack',
sex:'man'
}),
Map({
name:'Iric',
sex:'woman'
}),
Map({
name:'YOYO',
sex:'man'
})
])
const sexLIst = people.groupBy(item => item.get('sex'));
console.log(sexLIst.toJS())
二、 Map
Map对应原生Js的Object, 它是无序的。
1. 新建Map对象
map是工厂方法,无需使用new实例化。
const m1 = Map({ name:'Iric', age:20})
console.log('m1',m1)
2. set设定值 set(key, value)
const m2 = m1.set('sex','woman');
const m3 = m1.set(List([1]),{address:'陕西'});
console.log(m2.toJS())
console.log(m3.toJS())
3. get取值
const age = m2.get('age');
console.log(age) //20
4. delete删除值
delete(key)
const m4 = m3.delete('age');
console.log(m4.toJS())
5. deleteAll
批量删除
const names = iMap({ a: "Aaron", b: "Barry", c: "Connor" })
const res = names.deleteAll([ 'a', 'c' ])
console.log(res.toJS())
6. clear
清空Map,返回一个空Map
const names = iMap({ a: "Aaron", b: "Barry", c: "Connor" })
const cls = names.clear();
console.log('cls',cls.toJS()) //{}
7. update
update更新
update(key , callback)
const sal = Map({ name:'Iric', count:50})
const sale = sal.update('count', x=> x*10);
console.log(sale.toJS()) //name: "Iric", count: 500}
8. merge
把多个Map合并称一个Map
Map.merge(map1, map2,....)
const sal = Map({ name:'Iric', count:50})
const sal2 = Map({ sex:'man', address:'陕西'})
const sale = sal.merge(sal2)console.log(sale.toJS())
//{name: "Iric", count: 50, sex: "man", address: "陕西"}
9. mergeWith
和merge类似,但是指定了merge的规则。
const sal = Map({ name:'Iric', count:50})
const sal2 = Map({ sex:'man', address:'陕西', count: 15})
//表示如果有一样的属性,取sal2的count值,并且*20
const merge = sal.mergeWith((oldValue, newValue)=> {return newValue *20},sal2);
console.log(merge.toJS()) //{name: "Iric", count: 300, sex: "man", address: "陕西"}
10. setIn对于嵌套结构来进行设置值
setIn([层次1key, 层次2key, ...], value) 「同样操作的还有deleteIn、mergeIn、updateIn」
const deepMap = Map({
lev1: Map({
lev2: Map({
lev3: Map({
lev4: 'haha'
})
})
})
})
const setIn2 = deepMap.setIn(['lev1','lev2','lev3','lev4'],'嘿嘿')
console.log(setIn2.toJS())
11.toJS()
把Map转换成原生object, 深转换
const map1 = Map({ name:'Iric', age: 20})
console.log(map1.toJS()) //{name: "Iric", age: 20}
12. toJSON()
把Map转换成原生object, 浅转换
const map1 = Map({ name:'Iric', age: 20, address: Map({ add:'陕西' })})
console.log(map1.toJSON())
- toArray() 转化为原生数组
//浅转换
const person = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const person2 = person.toArray();console.log(person2) //["man", "shanxi", 15, "Iric"]
14. toObject
转化为原生object
const person = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const person2 = person.toObject();
console.log(person2) //{sex: "man", address: "shanxi", count: 15, name: "Iric"}
15. equels
判断2个map是否相等
const person1 = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const person2 = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
console.log('===', person1=== person2) //false
console.log('equals', person1.equals(person2)) //true
16. find
const person1 = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const name = person1.find((value, key) => value === 'Iric')
console.log(name) //Iric
17. has
判断是否含有指定的key
const person = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const person2 = person.has('name');
console.log(person2) //true
18. includes
是否含有指定的value
const person = Map({ sex:'man', address:'shanxi', count: 15, name:'Iric',});
const person2 = person.includes('Iric');
console.log(person2) //true
三、 Set
Set可以理解为value唯一的数组,即数组中不允许出现重复的值
1.新建Set
set是工厂方法,不允许new来实例化
const set = Set([1,2,3,5,2,3]);
console.log(set.toJS()) //[1, 2, 3, 5]
2. add添加值
const set2 = set.add('66');
console.log(set2.toJS()) //[1, 2, 3, 5, "66"]
3. delete删除之
set.delete(index)
const set3 = set.delete(1);
console.log(set3.toJS()) //[5, 2, 3] 无序的
4. clear清空并且返回一个空的set
const set4 = set.clear();
console.log(set4.toJS())
//[]
const set1 = Set([1,2,3,5,2,3]);
const set2 = Set(['aa','bb',2,3]);
5. union 把多个Set合并成一个Set
const union = set1.union(set2);
console.log(union.toJS()) //[1, 2, 3, 5, "aa", "bb"]
6. intersect 取N个Set的交集
const intersect = set1.intersect(set2);
console.log(intersect.toJS()) //[3, 2]
7.substract 从Set中去除一些值
const substract = set1.subtract([1,2,3])
console.log(substract.toJS()) //[5]
8.forEach
set1.forEach((key, value) => {
console.log(key, value)
})
参考文档:
- cloud.tencent.com/developer/s…
- immutable-js.github.io/immutable-j…
希望看到这里朋友可以动动手点个赞👍哦,你们的支持就是对我最大的鼓励💪!!!