說immutable以前,首先看下什麼是mutable。js在原生建立數據類型便是mutable,可變的。
const只是淺層次的防篡改,層級一深就沒轍了。html
js在建立變量、賦值後是可變的。除了基本類型,其餘的引用類型,經過變量地址來共享。
改變了obj1.a的值,同時也會改變obj.a的值。其實改變的是同一個對象引用。這樣共享地址來共享值的好處是節省內存,壞處是稍微不注意就會致使改A壞B的棘手問題。react
通常的解法就是使用深拷貝而非淺拷貝,生成一份基本類型值徹底相同可是沒有共享地址的數據,除了浪費內存以外,深拷貝複雜引用類型時須要深度遍歷,這樣的作法在React這樣頻繁更新數據和對數據更新性能有要求的場景,深拷貝是一個不優雅不推薦,say no的選擇。
那怎麼作呢,這個時候Immutable就能夠閃亮登場解決這個問題,爲何呢?git
相對於mutable,Immutable就是在建立變量、賦值後便不可更改,若對其有任何變動,就會回傳一個新值
Immutable只是一個定義,有各類實現,Immutable.js就是facebook工程師實現js的Immutable歷時三年的燒腦之做。甚至有些語言天生就是不可變數據結構,好比國內react的早期先驅題葉極力推崇的ClojureScript。
每次返回新值,你們可能會以爲性能也並很差啊,又佔內存之類的。若是實現告終構共享,每次的新值共享內部結構以大幅減小內存佔用。這意味着,若是對一個Immutable進行賦值1000次,並不會建立1000倍大小的內存佔用數據。github
與原生JS的mutable語義強烈衝突
除非從零開始一個項目,否則這種使用致使咱們可能用混,第三方庫也只支持原生js對象。
咱們須要採用一些手段來規避用混。算法
https://codesandbox.io/s/yq872yrlnx性能優化
真正的結構共享vs對象代理的僞實現數據結構
結構共享是指沒有改變的數據共用一個引用,這樣既減小了深拷貝的性能消耗,也減小了內存。app
extend https://reactjs.org/docs/update.htmlless
熟悉 React 的都知道,React 作性能優化時有一個避免重複渲染的大招,就是使用 shouldComponentUpdate(),但它默認返回 true,即始終會執行 render() 方法,而後作 Virtual DOM 比較,並得出是否須要作真實 DOM 更新,儘管React的虛擬算法複雜度已經有了不少優化,可是在大規模組件更新時,依然會是個沒必要要的損耗。會帶來不少無必要的渲染併成爲性能瓶頸。
咱們經常使用的Purecomponent的祕密實際上是在shouldComponentUpdate中作了先後state和props的淺比較,若是不當心組件props的引用問題,這裏會致使出現不少Bug。
雖然第一層數據沒變,但引用變了,就會形成虛擬 DOM 計算的浪費。
第一層數據改變,但引用沒變,會形成不渲染,因此須要很當心的操做數據。post
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; }
確保對象不可變的分三步:
精讀 Immutable 結構共享 https://juejin.im/entry/59b5e...
深刻探究Immutable.js的實現機制 https://juejin.im/post/5b9b30...
瞭解Clojure的持久變量 https://hypirion.com/musings/...
(此文由PPT摘抄完成)PPT連接