02基础操作

一个说明不可变的例子

// 如果只改变 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 有序集合,使用unshiftshift进行操作
  • 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()

  1. 接受两个参数
  • json 数据
  • reviver 函数
  1. 在不传递 reviver 函数的情况下,默认将原生JS的 Array 转化成 List, Object 转化成 Map
  2. 其他原生类型原封不动返回

is()

  1. Immutable 数据不应该被看成对象,应该看成该事件在特定时刻的状态
  2. 使用Immutable.is()两个参数,不仅可以比较 Immutable 类型的数据

Map

  1. 对应的是 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

  1. 有序 Map
  2. 顺序按 添加或声明 的顺序
  3. 会消耗更多内存
  4. 如果要求遍历有序,请使用 List

List

和原生 Array 最大的区别,不产生空位,即没有[,,,]

API

构造函数 Map() List()

  1. 该构造函数不常用
  2. 同key覆盖

另一种方式 of()

  1. 通过Map.of()
  2. 通过List.of()

判断是否是一个 Map 或者 List

  1. Map.isMap()
  2. List.isList()

获取大小

Immutable 对象上的属性和方法

  1. 属性size
  2. count方法,可以传入函数
  3. countBy方法,返回一个对象

添加元素

使用 set 不仅可以添加数据,还可以改变数据

  1. set在 List 中,使用索引,在 Map 中,使用属性
  2. setIn 第一个参数是路径

List 特有的添加元素

因为 List 是有原生JS数组转化,因此有很多添加元素的方法

  1. inset(inex,value)
  2. setSize(length),当设置很长的时候,会填充undefined
  3. pop/push/shift/unshift删除和添加元素
  4. 花样插入
  • interpose(separator)每两项中间添加 separator
  • interleave(immutable List)被操作的两个数组,每个的第一项,第二项,第三项...组成新的数组
  • zip(),被操作的两个数组,抽离第一项和第二项组成新的子数组,放入到一个大数组中,形成二维数组
  • zipWith(),自定义插入规则

删除元素

  1. delete()
  2. deleteIn() 使用方式和上边的 setIn 一样
  3. clear()

修改元素

  1. set/setIn
  2. update()
  3. updateIn()
// 第一个是要改变的数组项对应的索引,第二个是找不到对应数组项时的默认值,第三个是带默认参数的函数
update(key: K, notSetValue: V, updater: (value: V) => V): Map<K, V>

获取某个元素值

  1. get(key,notSetValue)只有数组可以key可以使用 number,即使对象{1:'hehe'}也是不能数 number 类型的1,需要用 string 类型的1
  • notSetValue 获取不到时的默认值
  1. getIn()
  2. first()获取头元素
  3. last()获取尾元素

查找某个元素

  1. find(function (val,index,array) {})可以自定义查找条件,比如索引,数值。返回value。findLast()使用方式同上,是倒序
  2. findKey(function (val,index,array) {})自定义查找条件,返回key。findLastKey()使用方式同前边,但是是倒序
  3. findEntry()返回 [key,value]findLastEntry()是倒序。注意,示例中,value好像不是数组项或者对象属性值,而是Immutable 数据类型。
  4. 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有键

  1. indexOf()根据index返回value。lastIndexOf()
  2. findIndex()返回inex,使用方式findIndex(function (val,index,arr){}),有些和findKey()相似。findLastIndex()倒序

查找最大,最小元素

  1. max()可以直接使用,可以传入一个自定义规则的函数
  2. maxBy()可以自定义比较元素和自定义比较规则。
  3. min()
  4. 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

  1. 三个分别获取的是
  • 对象键
  • 对象值
  • 对象键值组合[key,value]

截取

  1. slice(start,end)和原生的slice用法一致
  2. rest()返回删除第一个元素后的 List 或者 Map
  3. butLast() 返回删除最后一个元素的 List 或者 Map
  4. skip()从头按照条件抛出number个元素,截取剩余元素
  5. skipLast()从尾按照条件抛出number个元素,截取剩余元素
  6. skipWhile(function (val,index,obj) {})字面意思,当满足条件时,跳。从头开始,需要连续抛出return true的元素,中间断开后,再有return true也不抛出。然后返回剩余元素
  7. skipUntil(function (val,index,obj) {})字面意思,除了什么,其余跳。从头开始,需要连续抛出return false的元素,中间断开后,再有return false也不抛出。然后返回剩余元素。
  8. take()从头开始获取几个元素
  9. takeLast()从尾部开始获取几个元素
  10. takewhile(function (val,index,obj) {})从头开始,获取满足return true的元素
  11. takeUntil()从头开始,获取满足return false的元素

循环遍历

  1. map(function (val,index,array) {})
  2. filter()
  3. every()
  4. some()
  5. forEach()
  6. reduce()作用和原生Array 的 reduce相同
  7. recuceRight()

Map 特有的 mapKeys()/mapEntries()

  1. 对 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/mergeWithmergeDeep/mergeDeepWidth

  1. 在帖子中,按照两者均有上述方法, 但是文档中 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

配对使用

  1. 当转换成可变对象的,obj.set()会改变 obj 本身,也会生成一个改变后的对象
  2. 当转换成不可变对象时,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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容