开工大吉~🧧~🧧~

232 阅读7分钟

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())
  1. 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…

希望看到这里朋友可以动动手点个赞👍哦,你们的支持就是对我最大的鼓励💪!!!