一个说明不可变的例子
// 如果只改变 Immutable 对象的某个节点,那么该节点和父节点改变,其他共享
let a = Immutable.formJS({
naem: 'yf',
age: 19,
friend: {
name: 'yhx',
age: 9
}
})
let b = a.set('name':'yy');
console.log(a === b); // false
console.log(a.get('friend') === b.get('friend'))
immutable中的数据结构
常用的也就是 List , Map ,顶多加个 Seq
- List 有序索引集,类似于
Array
- Map 类似于
Object
- OrderedMap 有序 Map,排序依据是数据的
set()
操作 - Set 类似于ES6中
set
,不重复无序值的集合 - OrderedSet 有序 Set,排序依据是数据的
add
操作 - Stack 有序集合,使用
unshift
和shift
进行操作 - Seq 序列
- Range() 返回一个
Seq.Indexed
类型的数据结合,该方法接受三个参数(start = 1,end = infinity,step = 1)
,分别表示起始点/终止点和补偿,如果start
等于end
,则返回空的数据集合 - Repeat() 返回一个
Seq.indexed
类型的数据集合,该方法接受两个参数(value,times)
,value
表示重复生成的值,times
表示重复生成的次数,没有则表示生成无限个 - Record 类似于 ES6 中的 Class,但在细节上还有所不同
- Iterable 可以被迭代的
(key,value)
键值对结合,是基类,为其他所有集合提供了基础的Iterable
操作函数(比如 map 和 filter) - Collection 创建 Immutable 对象最基础的抽象类,不能直接构造该类型
几个重要的API
fromJS()
- 接受两个参数
- json 数据
- reviver 函数
- 在不传递 reviver 函数的情况下,默认将原生JS的 Array 转化成 List, Object 转化成 Map
- 其他原生类型原封不动返回
is()
- Immutable 数据不应该被看成对象,应该看成该事件在特定时刻的状态
- 使用
Immutable.is()
两个参数,不仅可以比较 Immutable 类型的数据
Map
- 对应的是 Map 数据类型,对应原生 Object ,对象 key 可是是任意值
console.log(Map().set(List.of(1),'list-of-one').get(List.of(1)))
console.log(Map().set(NaN,'NaN').get(NaN));
console.log(Map().set(undefined,'undefined').get('undefined'));
简单介绍 OrderMap
- 有序 Map
- 顺序按 添加或声明 的顺序
- 会消耗更多内存
- 如果要求遍历有序,请使用 List
List
和原生 Array 最大的区别,不产生空位,即没有[,,,]
API
构造函数 Map() List()
- 该构造函数不常用
- 同key覆盖
另一种方式 of()
- 通过
Map.of()
- 通过
List.of()
判断是否是一个 Map 或者 List
Map.isMap()
List.isList()
获取大小
Immutable 对象上的属性和方法
- 属性
size
-
count
方法,可以传入函数 -
countBy
方法,返回一个对象
添加元素
使用 set 不仅可以添加数据,还可以改变数据
-
set
在 List 中,使用索引,在 Map 中,使用属性 -
setIn
第一个参数是路径
List 特有的添加元素
因为 List 是有原生JS数组转化,因此有很多添加元素的方法
inset(inex,value)
-
setSize(length)
,当设置很长的时候,会填充undefined -
pop/push/shift/unshift
删除和添加元素 - 花样插入
-
interpose(separator)
每两项中间添加 separator -
interleave(immutable List)
被操作的两个数组,每个的第一项,第二项,第三项...组成新的数组 -
zip()
,被操作的两个数组,抽离第一项和第二项组成新的子数组,放入到一个大数组中,形成二维数组 -
zipWith()
,自定义插入规则
删除元素
delete()
-
deleteIn()
使用方式和上边的 setIn 一样 clear()
修改元素
set/setIn
update()
updateIn()
// 第一个是要改变的数组项对应的索引,第二个是找不到对应数组项时的默认值,第三个是带默认参数的函数
update(key: K, notSetValue: V, updater: (value: V) => V): Map<K, V>
获取某个元素值
-
get(key,notSetValue)
只有数组可以key可以使用 number,即使对象{1:'hehe'}
也是不能数 number 类型的1,需要用 string 类型的1
- notSetValue 获取不到时的默认值
getIn()
-
first()
获取头元素 -
last()
获取尾元素
查找某个元素
-
find(function (val,index,array) {})
可以自定义查找条件,比如索引,数值。返回value。findLast()
使用方式同上,是倒序 -
findKey(function (val,index,array) {})
自定义查找条件,返回key。findLastKey()
使用方式同前边,但是是倒序 -
findEntry()
返回[key,value]
。findLastEntry()
是倒序。注意,示例中,value好像不是数组项或者对象属性值,而是Immutable 数据类型。 -
keyOf()
根据value返回key。lastKeyOf()
倒序
// List
console.log(Immutable.fromJS([1, 2, 3, {a: {b: 111}}]).findEntry((value, index, array) => {
return index === 3;
}));// [3, Map]
// Map
console.log(Immutable.fromJS({a: {a1: 222}, b: 2, c: 3, d: 444}).findEntry((value, key, obj) => {
return Immutable.is(value, Immutable.fromJS({a1: 222}));
}));// ["a", Map]
List 特有查找某个元素
和索引有关的方法,因为list有索引,map有键
-
indexOf()
根据index返回value。lastIndexOf()
-
findIndex()
返回inex,使用方式findIndex(function (val,index,arr){})
,有些和findKey()
相似。findLastIndex()
倒序
查找最大,最小元素
-
max()
可以直接使用,可以传入一个自定义规则的函数 -
maxBy()
可以自定义比较元素和自定义比较规则。 min()
minBy()
// 自定义比较的元素,和比较规则
console.log(Immutable.fromJS([{a: 2}, {a: 1}, {a: 2301}, {a: 222}]).maxBy((value, index, array) => {
// 自定义比较元素
return value.get('a');
}, (valueA, valueB) => {
// 自定义比较规则
return valueA > valueB;
}).toJS());// {a: 2301}
生成迭代器
keys(),values(),entries() 这几个都会生成迭代器,可以使用
for of
- 三个分别获取的是
- 对象键
- 对象值
- 对象键值组合
[key,value]
截取
-
slice(start,end)
和原生的slice
用法一致 -
rest()
返回删除第一个元素后的 List 或者 Map -
butLast()
返回删除最后一个元素的 List 或者 Map -
skip()
从头按照条件抛出number个元素,截取剩余元素 -
skipLast()
从尾按照条件抛出number个元素,截取剩余元素 -
skipWhile(function (val,index,obj) {})
字面意思,当满足条件时,跳。从头开始,需要连续抛出return true
的元素,中间断开后,再有return true
也不抛出。然后返回剩余元素 -
skipUntil(function (val,index,obj) {})
字面意思,除了什么,其余跳。从头开始,需要连续抛出return false
的元素,中间断开后,再有return false
也不抛出。然后返回剩余元素。 -
take()
从头开始获取几个元素 -
takeLast()
从尾部开始获取几个元素 -
takewhile(function (val,index,obj) {})
从头开始,获取满足return true
的元素 -
takeUntil()
从头开始,获取满足return false
的元素
循环遍历
map(function (val,index,array) {})
filter()
every()
some()
forEach()
-
reduce()
作用和原生Array 的reduce
相同 recuceRight()
Map 特有的 mapKeys()/mapEntries()
- 对 Map 对象进行处理,返回新的对象
// mapKeys()
Immutable.fromJS({a:5,b:2}).mapKeys((key)=>{
return key + 'hehe';
})// {ahehe:5,bhehe:2}
// mapEntries()
Immutable.fromJS({a:5,b:2}).mapEntries(([key,val])=>{
return [key+'aaa',value+'bbbb'];
})// {aaaa:5bbbb,baaa:2bbbb}
merge
在 Map 类型的中有
merge/mergeWith
和mergeDeep/mergeDeepWidth
- 在帖子中,按照两者均有上述方法, 但是文档中 Map 和 List 方法是不同的
// merge 使用方式普通
const one = Map({ a: 10, b: 20, c: 30 })
const two = Map({ b: 40, a: 50, d: 60 })
one.merge(two) // Map { "a": 50, "b": 40, "c": 30, "d": 60 }
// mergeWith 使用的第一个参数是函数
const one = Map({ a: 10, b: 20, c: 30 })
const two = Map({ b: 40, a: 50, d: 60 })
one.mergeWith((oldVal, newVal) => oldVal / newVal, two)// { "a": 0.2, "b": 0.5, "c": 30, "d": 60 }
// 剩余两个只是深度合并
转化成字符串
join(separator)
判断是否为空
mapObj/listObj.isEmpty()
检查是否有某个key值
has()
-
hasIn([path])
这个是深度的检测
是否有某个value值
includes()
contains
- 这两个方法的参数可以是普通值,可以是 Immutable 中的数据结构
是否是子集
-
isSubSet()
判断方法的使用者是不是参数的子集
反转
reverse()
排序
-
sort()
可以传入参数,自定义排序规则 -
sortBy()
可以传入参数,自定义排序关键字和排序规则
console.log(Immutable.fromJS([{a: 1, b: {c: 22}}, {a: 2, b: {c: 22}}, {a: 1, b: {c: 22}},
{a: 3, b: {c: 22}}, {a: 10, b: {c: 22}}, {a: 9, b: {c: 22}}]).sortBy((value, index, array)=> {
// 排序关键字 value 就是数组的每一项,然后获取 a 就是依据 a 进行排序
return value.get('a')
},(a, b) => {
// -1 是不换位
if (a < b) {
return -1;
}
if (a > b) {
// 1 是换位
return 1;
}
if (a === b) {
return 0;
}
}).toJS());
// 升序 [{a:1,b:{c:22}},{a: 1, b: {c: 22}},{a: 2, b: {c: 22}}, {a: 3, b: {c: 22}},{a: 9, b: {c: 22}},{a: 10, b: {c: 22}}]
平铺
-
flatten()
默认参数值是false,深度平铺.传入参数true,平铺一层 - 平铺一层时,还有对象没有平铺开,就会显示为对象,Object.还有数组没有平铺开,就会显示为数组 Array
// List
console.log(Immutable.fromJS([1, 2, 3, 4, [1, 11, 111, 12344], {a: 1234, b: {bb: [777, 888]}}, 5, 6]).flatten().toJS());
// [1, 2, 3, 4, 1, 11, 111, 12344, 1234, 777, 888, 5, 6]
console.log(Immutable.fromJS([1, 2, 3, 4, [1, 11, 111, 12344], {a: 1234, b: {bb: [777, 888]}}, 5, 6]).flatten(true).toJS());
// [1, 2, 3, 4, 1, 11, 111, 12344, 1234, Object, 5, 6]
分组
-
groupBy()
返回的对象是 OrderedMap.根据自定义规则,选定分组的关键字,然后分组
console.log(Immutable.fromJS([{v: 0, a: 111}, {v: 1, a: {b: [1, 2, 3]}}, {v: 1, a: 333}, {v: 0, a: {b: [1, 2, 3]}}, {v: 1, a: 333}]).groupBy((value) => {
return value.get('a')
}).toJS());
// OrderedMap {111: Array[1], 333: Array[2], Map { "b": List [ 1, 2, 3 ] }: Array[2]}
// 含义: 根据 a 的值进行分组。其中,值为 111 的有一个,所以是长度为1的数组。其中第三个是,值为 Map { "b": List [ 1, 2, 3 ] } 的有两个,所以对应长度为2的数组
Map 特有的翻转
-
filp
键值翻转,应该保证值是唯一的
console.log(Immutable.fromJS({b: 'b1', a: 'a1', c: 'c1', d: 'd1'}).flip().toJS()); // {b1: "b", a1: "a", c1: "c", d1: "d"}
连接
concat()
类型转换
转化成js对象
-
toArray()
浅层,转化不了的保留Map或者list -
toObject()
浅层 -
toJS()
深层,少用
console.log(Immutable.fromJS([1, 2, 3, 4, 5, 6, {a: {b: [1234, 22]}}]).toArray());// [1, 2, 3, 4, 5, 6, Map]
console.log(Immutable.fromJS([1, 2, 3, 4, 5, 6, [1234, 22]]).toArray());// [1, 2, 3, 4, 5, 6, List]
转化成 Immutable 其他对象
- toMap()
- toOrderedMap()
- toSet()
- toOrderedSet()
- toList()
- toStack()
性能优化,批处理
当使用 push 在 list 上多次操作,会产生多个中间状态的 list,其实只需要最后一个,其他是冗余的。此时可以使用多种解决方式
withMutations
参数是一个函数
const $list1 = Immutable.List.of(1,2,3);
const $list2 = $list1.withMutations(function ($list) {
$list.push(4).push(5).push(6);
// 为此 withMutations 函数把list临时变为可变的数据,这三次push实质上只产生了一个中间态list
});
console.log($list1.size);// 3
console.log($list2.size);// 6
asMutable 和 asImmutable
配对使用
- 当转换成可变对象的,
obj.set()
会改变 obj 本身,也会生成一个改变后的对象 - 当转换成不可变对象时,
obj.set()
不会改变 obj 本身,但是会生成一个改变后的对象
const $test1= Immutable.List.of(1,2,3);
const $test2 = $test1.asMutable(); // $test2 变成可变对象
console.log($test1 === $test2); // false
console.log(Immutable.is($test1,$test2)); //true
// 当可变对象改变的时候
const $test3 = $test2.set(0,123);
console.log($test3 === $test2);//true
console.log(Immutable.is($test3,$test2));// true
// 转变成不可变的对象
const $test4 = $test3.asImmutable();
console.log($test3 === $test4);//true
console.log(Immutable.is($test3,$test4));// true
const $test5 = $test4.set(0,234);
console.log($test4 === $test5);//true
console.log(Immutable.is($test4,$test5));// true
网友评论