为什么 react要使用immutable.js

原文来自:https://zhuanlan.zhihu.com/p/29983598

首先有一个非常巨大的对象…

这里有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。


用普通的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会从旧对象(浅)复制每个属性到新的对象。

我们有100,000条待办事项,所以意味着有100,000个属性需要被(浅)复制。

这就是为什么花了这么长时间的原因。

在JavaScript中,对象默认是可变的。

当你复制一个对象时,JavaScript不得不复制每一个属性来保证这两个对象相互独立。

image.png

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倍。

为什么会这么快呢?


可持久化的数据结构

可持久化的数据结构强制约束所有的操作将返回新版本数据结构并且保持原有的数据结构不变,而不是直接修改原来的数据结构。

这意味着所有的可持久化数据结构是不可变的。

鉴于这个约束,第三方库在应用可持久化数据结构后可以更好的优化性能。


性能提升

为了直观的观察,让我们尝试一个小小例子。

键值对映射数据:

image.png

我们可以用一个普通的JavaScript对象来保存:

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

转换成一棵数据树,像这样:

image.png

图片来源: 维基百科

通常来讲,你可以从根节点沿着上图的路径来获取你想要的值。

如果你想获取http://data.in,从根节点开始,沿着i,n,就可以到达值为5的节点。

如何去修改呢?

比如我们想把键为tea的值3改成14。

我要建造一个新的树,并且尽可能重用已经存在的节点

image.png

绿色表示新建的节点。


image.png

灰色的节点失去的索引,将会被回收

正如你所看到的,我们只是重新创建了4个新的节点来更新这个树。其他节点都被重用了。

这叫 结构共享

Immutable.js就是通过这种方式实现Immutable.Map。创建一个树,每个节点最多有32个分支。

image.png

这张图展示了一个真实的Immutable.Map

当我们更新一个节点,只有几个节点需要被重新创建。

Immutable.js通过创建多种类型的节点来保持树结构的紧凑和性能:

image.png

万物皆有两面性...
请不要认为这篇文章的意思是“你应该经常使用Immutable.js。”,准确的讲,我只是告诉你用它的所有好处,以及为什么要使用它。

当我在写代码的时候,我首先会用普通的JavaScript对象和数组,当我使用Immutable.js时,我需要非常确定,比如一个对象包含10,000个属性。我几乎从不使用Immutable.js,因为大多数时候的对象都很小。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容