zoukankan      html  css  js  c++  java
  • ImmutableJS

    引用大神的一句话:(具体是谁自己问度娘)
    Shared mutable state is the root of all evil(共享的可变状态是万恶之源)
    -- Pete Hunt
     
    JavaScript 中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。
    如 foo={a: 1}; bar=foo; bar.a=2 你会发现此时 foo.a 也被改成了 2
    虽然这样做可以节约内存,但当应用复杂后,这就造成了非常大的隐患,Mutable 带来的优点变得得不偿失。
    为了解决这个问题,一般的做法是使用 shallowCopy(浅拷贝)或 deepCopy(深拷贝)来避免被修改,但这样做造成了 CPU 和内存的浪费。
     
     

    什么是 IMMUTABLE DATA

    Immutable Data 就是一旦创建,就不能再被更改的数据。
    对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
    Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。
    同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。请看下面动画:
     
     
    推荐学习ImmutableJS就应该去官网上去学习,但是自己的英语有限,虽然过了四级,但是这玩意基本上没什么卵用??
    只能用一些拿来主义的东西。
    ImmutableJS 提供了 7 种不可修改的资料类型:List、Map、Stack、OrderedMap、Set、OrderedSet、Record。
    若是对 Immutable 物件操作都会回传一个新值。其中比较常用的有 List、Map 和 Set:
     
    - Map:类似于 key/value 的 object,在 ES6 也有原生 Map 对应
     
     
    const Map= Immutable.Map;

    // 1. Map 大小const map1 = Map({ a: 1 });
    map1.size// => 1

    // 2. 新增或取代 Map 元素// set(key: K, value: V)const map2 = map1.set('a', 7);
    // => Map { "a": 7 }

    // 3. 删除元素// delete(key: K)const map3 = map1.delete('a');
    // => Map {}

    // 4. 清除 Map 内容const map4 = map1.clear();
    // => Map {}

    // 5. 更新 Map 元素// update(updater: (value: Map<K, V>) => Map<K, V>)// update(key: K, updater: (value: V) => V)// update(key: K, notSetValue: V, updater: (value: V) => V)const map5 = map1.update('a', () => (7))
    // => Map { "a": 7 }

    // 6. 合并 Map const map6 = Map({ b: 3 });
    map1.merge(map6);
    // => Map { "a": 1, "b": 3 }
     
    - List:有序且可以重复值,对应于一般的 Array
     
    const List= Immutable.List;

    // 1. 取得 List 长度const arr1 = List([1, 2, 3]);
    arr1.size// => 3

    // 2. 新增或取代 List 元素内容// set(index: number, value: T)// 将 index 位置的元素替换const arr2 = arr1.set(-1, 7);
    // => [1, 2, 7]const arr3 = arr1.set(4, 0);
    // => [1, 2, 3, undefined, 0]

    // 3. 删除 List 元素// delete(index: number)// 删除 index 位置的元素const arr4 = arr1.delete(1);
    // => [1, 3]

    // 4. 插入元素到 List// insert(index: number, value: T)// 在 index 位置插入 valueconst arr5 = arr1.insert(1, 2);
    // => [1, 2, 2, 3]

    // 5. 清空 List// clear()const arr6 = arr1.clear();
    // => []
     
    - Set:没有顺序且不能重复的列表
     
    const Set= Immutable.Set;

    // 1. 建立 Setconst set1 = Set([1, 2, 3]);
    // => Set { 1, 2, 3 }

    // 2. 新增元素const set2 = set1.add(1).add(5);
    // => Set { 1, 2, 3, 5 } // 由于 Set 为不能重复集合,故 1 只能出现一次

    // 3. 删除元素const set3 = set1.delete(3);
    // => Set { 1, 2 }

    // 4. 取联集const set4 = Set([2, 3, 4, 5, 6]);
    set1.union(set4);
    // => Set { 1, 2, 3, 4, 5, 6 }

    // 5. 取交集set1.intersect(set4);
    // => Set { 2, 3 }

    // 6. 取差集set1.subtract(set4);
    // => Set { 1 }
     
     
    看到这里,你已经基本上掌握了,他的基本的API。但是这玩意写代码的时候说不定就冒出什么你不认识的API,
    举个栗子:
    const  map=Immutable.map();
    
    //...........
    
    
    map.getIn()
    

      immutableData.getIn(['a', 'b']) // {a:{b:2}} 得到2。访问深层次的key

     看到了吧,你还是不会的,加油学习吧
     
     
    ImmutableJS 的特性整理
     
    // 有些开发者在使用时会在 ``Immutable` 变数前加 `$` 以示区隔。

    const $obj = fromJS({
    a: 1
    });

    funcationA($obj);
    console.log($obj.get('a')) // 1
     
    1. Structural Sharing 为了维持资料的不可变,又要避免像 deepCopy 一样复制所有的节点资料而造成的资源损耗,在 ImmutableJS 使用的是 Structural Sharing 特性,亦即如果物件树中一个节点发生变化的话,只会修改这个节点和和受它影响的父节点,其他节点则共享。
    const obj = {
      count: 1,
      list: [1, 2, 3, 4, 5]
    }
    var map1 = Immutable.fromJS(obj);
    var map2 = map1.set('count', 4);

    console.log(map1.list === map2.list); // true
     
    1. Support Lazy Operation
    Immutable.Range(1, Infinity)
    .map(n => -n)
    // Error: Cannot perform this action with an infinite size.

    Immutable.Range(1, Infinity)
    .map(n => -n)
    .take(2)
    .reduce((r, n) => r + n, 0);
    // -3
     
    4.丰富的 API 并提供快速转换原生 JavaScript 的方式 在 ImmutableJS 中可以使用 fromJS()toJS() 进行 JavaScript 和 ImmutableJS 之间的转换。但由于在转换之间会非常耗费资源,所以若是你决定引入 ImmutableJS 的话请尽量维持资料处在 Immutable 的状态。
     
     
    5.支持 Functional Programming Immutable 本身就是 Functional Programming(函数式程式设计)的概念,所以在 ImmutableJS 中可以使用许多 Functional Programming 的方法,例如:mapfiltergroupByreducefindfindIndex 等。
     

    React 效能优化

    ImmutableJS 除了可以和 Flux/Redux 整合外,也可以用于基本 react 效能优化。以下是一般使用效能优化的简单方式:

    传统 JavaScript 比较方式,若资料型态为 Primitive 就不会有问题:

    // 在 shouldComponentUpdate 比较接下来的 props 是否一致,若相同则不重新渲染,提升效能shouldComponentUpdate (nextProps) {
        return this.props.value !== nextProps.value;
    }
    

    但当比较的是物件的话就会出现问题:

    // 假设 this.props.value 为 { foo: 'app' }// 假设 nextProps.value 为 { foo: 'app' },// 虽然两者值是一样,但由于 reference 位置不同,所以视为不同。但由于值一样应该要避免重复渲染this.props.value !== nextProps.value; // true
    使用 ImmutableJS
     
     
    var SomeRecord = Immutable.Record({ foo: null });
    var x = new SomeRecord({ foo: 'app'  });
    var y = x.set('foo', 'azz');
    x === y; // false
     
    在 ES6 中可以使用官方文件上的 PureRenderMixin 进行比较,可以让程式码更简洁:
     
    import PureRenderMixin from 'react-addons-pure-render-mixin';
    class FooComponent extends React.Component {
      constructor(props) {
        super(props);
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
      }
      render() {
        return <div className={this.props.className}>foo</div>;
      }
    }

     
     
     
     
     
     
     
     
     
     
     
     
    原生js转换为immutableData Immutable.fromJS([1,2]) // immutable的 list Immutable.fromJS({a: 1}) // immutable的 map 从immutableData 回到 JavaScript 对象 immutableData.toJS() 判断两个immutable数据是否一致 Immutable.is(immutableA, immutableB) 判断是不是map或List Immutable.Map.isMap(x) Immutable.Map.isList(x) 对象合并(注意是同个类型) immutableMaB = immutableMapA.merge(immutableMaC) Map的增删查改 查 immutableData.get('a') // {a:1} 得到1。 immutableData.getIn(['a', 'b']) // {a:{b:2}} 得到2。访问深层次的key 增和改(注意不会改变原来的值,返回新的值) immutableData.set('a', 2) // {a:1} 得到1。 immutableData.setIn(['a', 'b'], 3) immutableData.update('a',function(x){return x+1}) immutableData.updateIn(['a', 'b'],function(x){return x+1}) 删 immutableData.delete('a') immutableData.deleteIn(['a', 'b']) List的增删查改 如同Map,不过参数变为数字索引。 比如immutableList.set(1, 2) 其它便捷函数 如同underscore的方法,都有噢。
  • 相关阅读:
    2.12 使用@DataProvider
    2.11 webdriver中使用 FileUtils ()
    Xcode8 添加PCH文件
    The app icon set "AppIcon" has an unassigned child告警
    Launch Image
    iOS App图标和启动画面尺寸
    iPhone屏幕尺寸、分辨率及适配
    Xcode下载失败 使用已购项目页面再试一次
    could not find developer disk image
    NSDate与 NSString 、long long类型的相互转化
  • 原文地址:https://www.cnblogs.com/wy1935/p/7092911.html
Copyright © 2011-2022 走看看