#7 Immutable.js初步学习

作者: JamesSawyer | 来源:发表于2016-12-26 22:11 被阅读2476次

    初步阅读 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()

    相关文章

      网友评论

        本文标题:#7 Immutable.js初步学习

        本文链接:https://www.haomeiwen.com/subject/avksvttx.html