掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务

为什么用Immutable.js代替普通js对象?

本文由miaoyu 在众成翻译平台上翻译。

将数据视为不可变,将给你带来很多好处。事实上,这是也React背后的原理:React的元素是不可变的。

但是用Immutable.js有什么好处呢?


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

这里有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不得不复制每一个属性来保证这两个对象相互独立。

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,从根节点开始,沿着i,n,就可以到达值为5的节点。

如何去修改呢?

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

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

绿色表示新建的节点。

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

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

这叫 结构共享

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

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

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

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


万物皆有两面性...

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

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

原文来自:众成翻译

声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com

  • 个人/企业涉诉查询

    通过企业关键词查询企业涉松详情,如裁判文书、开庭公告、执行公告、失信公告、案件流程等等。

    通过企业关键词查询企业涉松详情,如裁判文书、开庭公告、执行公告、失信公告、案件流程等等。

  • 账号黑产风险识别

    根据手机号来查询是否命中黑产风险

    根据手机号来查询是否命中黑产风险

  • IP反查域名

    IP反查域名是通过IP查询相关联的域名信息的功能,它提供IP地址历史上绑定过的域名信息。

    IP反查域名是通过IP查询相关联的域名信息的功能,它提供IP地址历史上绑定过的域名信息。

  • 人脸卫士

    结合权威身份认证的精准人脸风险查询服务,提升人脸应用及身份认证生态的安全性。人脸风险情报库,覆盖范围广、准确性高,数据权威可靠。

    结合权威身份认证的精准人脸风险查询服务,提升人脸应用及身份认证生态的安全性。人脸风险情报库,覆盖范围广、准确性高,数据权威可靠。

  • 全国城市空气质量

    全国城市和站点空气质量查询,污染物浓度及空气质量分指数、空气质量指数、首要污染物及空气质量级别、健康指引及建议采取的措施等。

    全国城市和站点空气质量查询,污染物浓度及空气质量分指数、空气质量指数、首要污染物及空气质量级别、健康指引及建议采取的措施等。

0512-88869195
数 据 驱 动 未 来
Data Drives The Future