【Immutable.js】可持久化數據結構以及結構分享

爲何用Immutable.js代替普通js對象?

將數據視爲不可變,將給你帶來不少好處。事實上,這是也React背後的原理:React的元素是不可變的。git

可是用Immutable.js有什麼好處呢?github


首先有一個很是巨大的對象…

這裏有100,000條待辦事項:數組

var todos = {
  ⋮
  t79444dae: { title: 'Task 50001', completed: false },
  t7eaf70c3: { title: 'Task 50002', completed: false },
  t2fd2ffa0: { title: 'Task 50003', completed: false },
  t6321775c: { title: 'Task 50004', completed: false },
  t2148bf88: { title: 'Task 50005', completed: false },
  t9e37b9b6: { title: 'Task 50006', completed: false },
  tb5b1b6ae: { title: 'Task 50007', completed: false },
  tfe88b26d: { title: 'Task 50008', completed: false },
  ⋮
  (100,000 items)
}複製代碼

我要把第50,005條任務的completed改成ture。bash


用普通的JavaScript對象

function toggleTodo (todos, id) {
  return Object.assign({ }, todos, {
    [id]: Object.assign({ }, todos[id], {
      completed: !todos[id].completed
    })
  })
}

var nextState = toggleTodo(todos, 't2148bf88')複製代碼

這項操做運行了134ms數據結構

爲何用了這麼長時間呢?由於當使用Object.assign,JavaScript會從舊對象(淺)複製每一個屬性到新的對象。svg

咱們有100,000條待辦事項,因此意味着有100,000個屬性須要被(淺)複製。性能

這就是爲何花了這麼長時間的緣由。優化

在JavaScript中,對象默認是可變的。ui

當你複製一個對象時,JavaScript不得不復制每個屬性來保證這兩個對象相互獨立spa

100,000個屬性被(淺)複製到新的對象。


使用Immutable.js

var todos = Immutable.fromJS({
  ⋮
  t79444dae: { title: 'Task 50001', completed: false },
  t7eaf70c3: { title: 'Task 50002', completed: false },
  t2fd2ffa0: { title: 'Task 50003', completed: false },
  t6321775c: { title: 'Task 50004', completed: false },
  t2148bf88: { title: 'Task 50005', completed: false },
  t9e37b9b6: { title: 'Task 50006', completed: false },
  tb5b1b6ae: { title: 'Task 50007', completed: false },
  tfe88b26d: { title: 'Task 50008', completed: false },
  ⋮
  (100,000 items)
})

// 使用[updeep](https://github.com/substantial/updeep)
function toggleTodo (todos, id) {
  return u({
    [id]: {
      completed: (completed) => !completed
    }
  }, todos)
}

var nextState = toggleTodo(todos, 't2148bf88')複製代碼

這項操做運行了1.2ms。速度提高了100倍。

爲何會這麼快呢?


可持久化的數據結構

可持久化的數據結構強制約束全部的操做將返回新版本數據結構而且保持原有的數據結構不變,而不是直接修改原來的數據結構。

這意味着全部的可持久化數據結構是不可變的。

鑑於這個約束,第三方庫在應用可持久化數據結構後能夠更好的優化性能


性能提高

爲了直觀的觀察,讓咱們嘗試一個小小例子。

鍵值對映射數據:

咱們能夠用一個普通的JavaScript對象來保存:

const data = {
  to: 7,
  tea: 3,
  ted: 4,
  ten: 12,
  A: 15,
  i: 11,
  in: 5,
  inn: 9
}複製代碼

轉換成一棵數據樹,像這樣:


圖片來源: 維基百科

一般來說,你能夠從根節點沿着上圖的路徑來獲取你想要的值。

若是你想獲取data.in,從根節點開始,沿着in,就能夠到達值爲5的節點。

如何去修改呢?

好比咱們想把鍵爲tea的值3改爲14

我要建造一個新的樹,而且儘量重用已經存在的節點

綠色表示新建的節點。


灰色的節點失去的索引,將會被回收

正如你所看到的,咱們只是從新建立了4個新的節點來更新這個樹。其餘節點都被重用了。

這叫 結構共享

Immutable.js就是經過這種方式實現Immutable.Map。建立一個樹,每一個節點最多有32個分支。


這張圖展現了一個真實的 Immutable.Map

當咱們更新一個節點,只有幾個節點須要被從新建立。

Immutable.js經過建立多種類型的節點來保持樹結構的緊湊和性能:


萬物皆有兩面性...

請不要認爲這篇文章的意思是「你應該常常使用Immutable.js。」,準確的講,我只是告訴你用它的全部好處,以及爲何要使用它。

當我在寫代碼的時候,我首先會用普通的JavaScript對象和數組,當我使用Immutable.js時,我須要很是肯定,好比一個對象包含10,000個屬性。我幾乎從不使用Immutable.js,由於大多數時候的對象都很小。


感謝你的閱讀!

原文:medium.com/@dtinth/imm…

相關文章
相關標籤/搜索