Immutable

Part01 Immutable由何而生

说immutable以前,首先看下什么是mutable。js在原生建立数据类型便是mutable,可变的。
const只是浅层次的防篡改,层级一深就没辙了。html

mutable

js在建立变量、赋值后是可变的。除了基本类型,其余的引用类型,经过变量地址来共享。
改变了obj1.a的值,同时也会改变obj.a的值。其实改变的是同一个对象引用。这样共享地址来共享值的好处是节省内存,坏处是稍微不注意就会致使改A坏B的棘手问题。react

Deep Copy?No!

通常的解法就是使用深拷贝而非浅拷贝,生成一份基本类型值彻底相同可是没有共享地址的数据,除了浪费内存以外,深拷贝复杂引用类型时须要深度遍历,这样的作法在React这样频繁更新数据和对数据更新性能有要求的场景,深拷贝是一个不优雅不推荐,say no的选择。
那怎么作呢,这个时候Immutable就能够闪亮登场解决这个问题,为何呢?git

Part02 Immutable是个什么

immutable

相对于mutable,Immutable就是在建立变量、赋值后便不可更改,若对其有任何变动,就会回传一个新值

Immutable只是一个定义,有各类实现,Immutable.js就是facebook工程师实现js的Immutable历时三年的烧脑之做。甚至有些语言天生就是不可变数据结构,好比国内react的早期先驱题叶极力推崇的ClojureScript。
每次返回新值,你们可能会以为性能也并很差啊,又占内存之类的。若是实现告终构共享,每次的新值共享内部结构以大幅减小内存占用。这意味着,若是对一个Immutable进行赋值1000次,并不会建立1000倍大小的内存占用数据。github

与原生JS的mutable语义强烈冲突

除非从零开始一个项目,否则这种使用致使咱们可能用混,第三方库也只支持原生js对象。
咱们须要采用一些手段来规避用混。算法

  1. 使用类型系统,TypeScript或Flow。消除了Immutable流经系统的精神负担。代价是编写风格将颠覆式的彻底不一样。
  2. 隐藏有关数据结构的详细信息。若是您在系统的特定部分使用Immutable.js,请不要在其外部进行任何操做直接访问数据结构。一个很好的例子是Redux,它是单原子app状态。若是app状态是Immutable.js对象,请不要强制React组件直接使用Immutable.js的API。

vs

https://codesandbox.io/s/yq872yrlnx性能优化

真正的结构共享vs对象代理的伪实现数据结构

结构共享是指没有改变的数据共用一个引用,这样既减小了深拷贝的性能消耗,也减小了内存。app

extend https://reactjs.org/docs/update.htmlless

Part03 怎么用

与React搭配使用,关键点是shouldComponentUpdate

熟悉 React 的都知道,React 作性能优化时有一个避免重复渲染的大招,就是使用 shouldComponentUpdate(),但它默认返回 true,即始终会执行 render() 方法,而后作 Virtual DOM 比较,并得出是否须要作真实 DOM 更新,尽管React的虚拟算法复杂度已经有了不少优化,可是在大规模组件更新时,依然会是个没必要要的损耗。会带来不少无必要的渲染并成为性能瓶颈。
咱们经常使用的Purecomponent的秘密实际上是在shouldComponentUpdate中作了先后state和props的浅比较,若是不当心组件props的引用问题,这里会致使出现不少Bug。
虽然第一层数据没变,但引用变了,就会形成虚拟 DOM 计算的浪费。
第一层数据改变,但引用没变,会形成不渲染,因此须要很当心的操做数据。post

Object.assign能够实现不可变数据,惟一的就是性能问题

Part04 怎么实现

seamless-immutable

Object.freeze防止对象被修改
https://developer.mozilla.org...

function makeImmutable(obj, bannedMethods) {
  // 在对象上打上immutabilityTag标记即表示对象不可变
  addImmutabilityTag(obj);

  if (process.env.NODE_ENV !== "production") {
    // 让全部致使对象改变的方法在调用时抛出错误
    for (var index in bannedMethods) {
      if (bannedMethods.hasOwnProperty(index)) {
        banProperty(obj, bannedMethods[index]);
      }
    }
    // 冻结对象
    Object.freeze(obj);
  }
  return obj;
}

确保对象不可变的分三步:

  1. 打上immutabilityTag标记;
  2. 禁用会致使对象改变的方法;
  3. 冻结对象。

Immutable-js

精读 Immutable 结构共享 https://juejin.im/entry/59b5e...

深刻探究Immutable.js的实现机制 https://juejin.im/post/5b9b30...

了解Clojure的持久变量 https://hypirion.com/musings/...

完结

(此文由PPT摘抄完成)PPT连接

相关文章
相关标签/搜索