immutable.js 和 immer

不可變數(shù)據(jù)類型

immutable,副作用,純函數(shù)關(guān)鍵詞解釋:

  • immutable: 不可變數(shù)據(jù)
  • 副作用:調(diào)用函數(shù),同時(shí)對(duì)主函數(shù)產(chǎn)生了附加的影響,比如修改全局變量,改變參數(shù)。
    如何避免,創(chuàng)建不可變數(shù)據(jù)類型,在一次更新過程中不應(yīng)該改變原有對(duì)象,需要返回一個(gè)新的對(duì)象
  • 純函數(shù):無副作用的函數(shù)

js 中的對(duì)象一般是可變的,因?yàn)槭褂昧艘觅x值,雖然可以節(jié)約內(nèi)存,但是會(huì)有一些隱患。一般做法使用淺拷貝和深拷貝來避免修改,但是這樣會(huì)造成 CPU 和內(nèi)存浪費(fèi)。

為了解決這個(gè)問題,出現(xiàn)了 immutable.js 和 immer

immutable.js 庫

immutable.js 實(shí)現(xiàn)原理:Persistent Data Structure(持久化數(shù)據(jù)結(jié)構(gòu))。

  • 使用舊數(shù)據(jù)創(chuàng)建新數(shù)據(jù)時(shí),要保證舊數(shù)據(jù)同時(shí)可用且不變。同時(shí)為了避免 deepCopy 把所有節(jié)點(diǎn)否復(fù)制一遍帶來的性能問題, immutable 使用了 Structural Sharing(結(jié)構(gòu)共享),即如果對(duì)象樹中的一個(gè)節(jié)點(diǎn)改變,只修改這個(gè)節(jié)點(diǎn)和受它影響的父節(jié)點(diǎn),其他節(jié)點(diǎn)共享。
  • immutable-js 使用了另一套數(shù)據(jù)結(jié)構(gòu) api,它會(huì)將原生數(shù)據(jù)類型都轉(zhuǎn)化為 immutable-js 內(nèi)部對(duì)象。

內(nèi)部實(shí)現(xiàn)了一套 Persistent Data Structure,還有很多易用的數(shù)據(jù)類型像 Collection、ListMap、SetRecord、Seq。有非常全面的mapfilter、groupByreduce``find函數(shù)式操作方法。同時(shí) API 也盡量與 Object 或 Array 類似。

缺點(diǎn):

  1. 需要學(xué)習(xí)新的 API
  2. 容易與原生對(duì)象混淆。
    Immutable 中的 Map 和 List 雖對(duì)應(yīng)原生 Object 和 Array,但操作非常不同,比如你要用 map.get('key') 而不是 map.key,array.get(0) 而不是 array[0]。另外 Immutable 每次修改都會(huì)返回新對(duì)象,也很容易忘記賦值。

和 redux 的配合使用,redux 簡化了 Flux 中多個(gè) store 的概念,只有一個(gè) store,數(shù)據(jù)操作通過 reducer 使用。reducer 就是要接受一個(gè)純函數(shù)。

const reducer = function (state, action) {
  // ...
  return new_state;
};

immer

mobx 作者寫的一個(gè) immutable 庫,核心實(shí)現(xiàn)利用 es6 的 proxy。
immer 使用原生數(shù)據(jù)結(jié)構(gòu)的 api,而不像 immutable-js 轉(zhuǎn)化為內(nèi)置對(duì)象的 api。
學(xué)習(xí)成本低,就是把之前的操作放置到 produce 函數(shù)的第二參數(shù)函數(shù)中去執(zhí)行。
原理:使用了一個(gè) ES6 的新特性 Proxy 對(duì)象。深層嵌套對(duì)象的結(jié)構(gòu)化共享的處理

proxy 具體可以看 Proxy

var proxy = new Proxy(target, handler);
  • target 參數(shù)表示所要攔截的目標(biāo)對(duì)象。如果沒有 Proxy 的介入,操作原來要訪問的就是這個(gè)對(duì)象
  • handler 參數(shù)也是一個(gè)對(duì)象,用來定制攔截行為。對(duì)于每一個(gè)被代理的操作,需要提供一個(gè)對(duì)應(yīng)的處理函數(shù),該函數(shù)將攔截對(duì)應(yīng)的操作

Proxy 無法 polyfill,所以 immer 在不支持 Proxy 的環(huán)境中,使用 Object.defineProperty 來進(jìn)行一個(gè)兼容。

immer 維護(hù)一份 state 在內(nèi)部,劫持所有操作,內(nèi)部來判斷是否有變化從而最終決定如何返回。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文 我們知道 js 對(duì)象是按共享傳遞(call by sharing)的,因此在處理復(fù)雜 js 對(duì)象的時(shí)候,往往...
    videring閱讀 1,265評(píng)論 0 2
  • 本篇只是對(duì)Immutable.js的簡單介紹,后續(xù)會(huì)繼續(xù)分享其具體實(shí)踐應(yīng)用。 什么是Immutable Data?...
    桂圓_noble閱讀 48,605評(píng)論 4 67
  • js 對(duì)象深拷貝 JS 里面的變量類型可以分為 基本類型 和 引用類型 。在使用過程中,引用類型經(jīng)常會(huì)產(chǎn)生一些無法...
    車與路閱讀 1,419評(píng)論 2 4
  • React在減少重復(fù)渲染方面確實(shí)是有一套獨(dú)特的處理辦法,那就是虛擬DOM,但顯然在首次渲染的時(shí)候React絕無可能...
    Nosaj閱讀 709評(píng)論 0 2
  • 前言 React和Redux都遵守組件狀態(tài)為不可變(immutable)的理念,通常在修改state的時(shí)候都會(huì)使用...
    _stan閱讀 4,785評(píng)論 0 3

友情鏈接更多精彩內(nèi)容