#7 Immutable.js初步学习

初步阅读 Immutable.js官网文档, 作出如下记录,以便查阅。

1.fromJS()

深度的将数组转换成Immutable Lists,将对象转换成Immutable Maps。

语法:

fromJS(json: any, reviver?: (k: any, v: Iterable<any, any>) => any): any

reviver 为一个可选参数

示例:

Immutable.fromJS({
  a: {
    b: [1, 2, 3],
    c: 40
  }
});
// 得到
Map {
  "a": Map {
    "b": List [1, 2, 3],
    "c": 40
  }
}   

值得注意的是,将JS object转换成Immutable Maps时, JS对象的属性永远都是字符串,即使写为没有字符串的简写形式

var obj = {1: "one"};
var map = Map(obj);
map.get("1"); // "one"
map.get(1);   // undefined

2.is()

用于检测值的相等性,注意这和Object.is()的区别

语法:

is(first: any, second: any): boolean

示例:

var map1 = Immutable.Map({a: 1, b: 1});
var map2 = Immutable.Map({a: 1, b: 1});
map1 !== map2; // true
Object.is(map1, map2); // false
Immutable.is(map1, map2); // true 只检测值是否相等

另外注意这个差别:

Immutable.is(0, -0); // true
Object.is(0, -0); // false

List

List是有序索引密集的集合,和JS中的Array很像

定义:

class List<T> extends Collection.Indexed<T>

1.静态方法

1.List.isList()

判断一个集合是否为一个List集合

List.isList(maybeList: any): boolean

示例:

const plainArr = [1, 2, 3];
const listFromPlainArray = List(plainArr);
List.isList(listFromPlainArray); // true
listFromPlainArray.toJS(); // [1, 2, 3]

2.List.of()

创建一个新的List,并且包含values

List.of<T>(...values: T[]): List<T>

实例:

List.of(1, 2, 3, 4);
var myList = List.of({x: 1}, 2, [3]);
myList.toJS(); // [ {x: 1}, 2, [3] ]

1.Deep persistent changes

setIn()

keyPath的地方设置新的value,如果对应的keyPath中不存在keys,则返回一个新的immutable Map

语法:

setIn(keyPath: Array<any>, value: any): List<T>
setIn(keyPath: Iterable<any, any>, value: any): List<T>

// setIn([index(, otherIndex)], value)
表示对应的索引位置设置值

示例:

Immutable.fromJS([0, 1, 3, [5, 7]]).setIn([3, 2], 9).toJS(); // [0, 1, 3, [5, 7, 9]]

2.creating subsets

rest()

返回一个新的可循环的实体,除了第1个

var myList = List.of(1, 2, 3);
myList.rest().toJS(); // [2, 3]

butLast()

和上面的正好相反,除去最后一个

myList.butLast().toJS(); // [1, 2]

skip()

跳过的数量

myList.skip(2).toJS(); // [3]

skipWhile()

predicate函数开始返回 false时后面的实体

语法:

skipWhile(
  predicate: (value: T, key: number, iter: Iterable<number, T>) => boolean,
  context?: any
): Iterable<number, T>

示例:

Seq.of('dog', 'frog', 'cat', 'hat', 'god')
  .skipWhile(x => x.match(/g/));

// 到 'cat'时返回false, 所以返回
// Seq [ 'cat', 'hat', 'god']

skipUntil()

predicate函数开始返回 true时后面的实体

实例:

Seq.of('dog', 'frog', 'cat', 'hat', 'god')
  .skipUntil(x => x.match(/hat/))
// Seq ['hat', 'god']

zip()

使用默认的 zipper 函数对2个集合进行处理

var a = Seq.of(1, 2, 3, 4, 5);
var b = Seq.of('a', 'b', 'c');

var c = a.zip(b);
// Seq [ [1, 'a'], [2, 'b'], [3, 'c'] ]
// 多的部分省略掉了

zipWith()

和上面不同的时,这个可以自定义 zipper 函数, 按照自己的逻辑进行处理集合

var a = Seq.of(1, 2, 3);
var b = Seq.of(4, 5, 6);
// (x, y) => x + y 表示的是zipper函数
// b 表示的是第2个集合
var c = a.zipWith((x, y) => x + y, b);
// Seq [5, 7, 9]

Map

Map集合和List集合的静态方法基本相似,Map.isMap() | Map.of(),这个是针对对象而言

update()

如果存在相应的key,则通过 updater 对其进行更新,并返回更新后的新的Map;如果没有定义key,则更新的为Map自身

3种语法:

update(updater: (value: Map<K, V>) => Map<K, V>): Map<K, V>
update(key: K, updater: (value: V) => V): Map<K, V>
update(key: K, notSetValue: V, updater: (value: V) => V): Map(K, V)

示例:

#1 不设置key,对整个Map集合进行更新
// 相当于 map.set(key, updater(map.get(key, notSetValue)))
const originalMap = Immutable.Map({
  key: 'value',
  subObject: { subKey: 'subValue' }
});

const newMap = originalMap.update(map => {
  return Immutable.Map(map.get('subObject'))
});
newMap.toJS(); // { subKey: 'subValue'}

#2 对存在的key进行更新
const newMap = originalMap.update('key', value => value + value);
newMap.toJS(); 
// {
     key: 'valuevalue', 
     subObject: { subkey: 'subValue'}
   }

#3 对不存在的key,进行更新
var originalMap = Immutable.Map({
  key: 'value'
});
var newMap = originalMap.update('noKey', 'noValue', value => value + value);
newMap.toJS();
// {
     key: 'value',
     noKey: 'no valueno value'
   }

mergeDeep

当2个集合产生了冲突, 将递归合并嵌套的数据

示例:

var x = Immutable.fromJS({
  a: { x: 10, y: 10 },
  b: { x: 20, y: 50 }
});
var y = Immutable.fromJS({
  a: { x: 2 },
  b: { y: 5 },
  c: { z: 3 }
});
x.mergeDeep(y);
// 结果
Map {
  a: { x: 2, y: 10 },
  b: { x:20, y: 5 },
  c: { z: 3 }
}

setIn()

根据 keyPath 来设置 value, 如果对应的 keyPath不存在,则创建新的 key

示例:

#1 'keyPath' 存在的情况
const originalMap = Immutable.fromJS({
  subObject: {
    subKey: 'subValue',
    subSubObject: {
      subSubKey: 'subSubValue'
    }
  }
});

const newMap = originalMap.set(['subObject', 'subSubObject', 'subSubKey'], 'great');
newMap.toJS();
subObject: {
    subKey: 'subValue',
    subSubObject: {
      subSubKey: 'great'
    }
  }

#2 'keyMap'不存在的情况
var map = Immutable.fromJS({
  a: 'hello',
  b: {
    x: 12,
    y: 34
  }
});
var newMap = map.setIn(
  ['b', 'z'],
  50
);
newMap.toJS();
{
  a: 'hello',
  b: {
    x: 12,
    y: 34,
    z: 50
  }
}

Transient changes

1.withMutation

如果想应用一系列可变操作产生一个新的immutable Map,可以使用 withMutation 来产生一个中间可变Map。只有 set ,merge 方法能用在中间可变的集合中

示例:

var map1 = Immutable.Map();
var map2 = map1.withMutation(map => {
  map.set('a', 1).set('b', 2).set('c', 3)
});
map2.toJS();
{
  a: 1,
  b: 2,
  c: 3
}

Range()

返回一个 Seq 集合, 从 start (inclusive, 默认是0)end (exclusive, 默认是infinity), by step(默认值是1).当 start === end 时,返回一个空的range

语法:

Range(start?: number, end?: number, step?: number): Seq.Indexed<number>

示例:

Range(); // Seq [0, 1, 2....]
Range(10, 15); // Seq [10, 11, 12, 13, 14]
Range(10, 30, 5);  // Seq [10, 15, 20, 25]
Range(30, 10, 5); // Seq [30, 25, 20, 15]
Range(30, 30); Seq []

Iterable

Iterable 是一系列能够迭代的键值对,是immutable.js中所有集合的基类,从而使得所有的集合都拥有可迭代的方法(比如map, filter)

class Iterable<K, V>

静态方法

Iterable.isIterable()

示例:

var Iterable = Immutable.Iterable;

Iterable.isIterable([]); // false
Iterable.isIterable({}); // false
Iterable.isIterable(Immutable.Map()); // ture
Iterable.isIterable(Immutable.List()); // ture
Iterable.isIterable(Immutable.Seq()); // ture
Iterable.isIterable(Immutable.Stack()); // ture

Collection

Collection对实体数据结构是个抽象基类,不能够直接的构建

class Collection<K, V> extends Iterable<K, V>

总结

immutable.js 对于数据的操作都是同个集合的方式来完成。对于数据无非就是增删改查, immutable.js最大的优点就是不会改变原有的数据,都是通过返回新的集合类型来完成的。另外提供了大量的方法来操作数据。

比较最要的集合有List, Map。然后就是几种方法,比如对于集合和常规的JS对象数组的转换,会使用到 Immutable.fromJS() | Immutable.toJS()

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

推荐阅读更多精彩内容