为什么我要在object.freeze上使用immutablejs?

ali*_*ari 30 javascript reactjs immutable.js

我已经在网上研究过immutablejs的好处,Object.freeze()但没有找到令人满意的东西!

我的问题是,当我可以冻结一个普通的旧javascript对象时,为什么我应该使用这个库并使用非本机数据结构?

Zir*_*rak 56

我不认为你理解immutablejs提供的东西.它不是一个只能将对象变为不可变的库,它是一个围绕使用不可变值的库.

不仅仅重复他们的文档使命陈述,我将陈述它提供的两件事:

  1. 类型.他们实现了(不可变的)无限范围,堆栈,有序集,列表,......

  2. 它们的所有类型都实现为持久数据结构.

我撒了谎,这是他们的使命宣言的引用:

创建后不可更改不可变数据,从而使应用程序开发更加简单,无需防御性复制,并且可以通过简单的逻辑实现高级存储和更改检测技术.持久性数据提供了一个变异的API,它不会就地更新数据,而是始终产生新的更新数据.

我恳请你阅读他们链接的文章和视频以及更多关于持久性数据结构的内容(因为它们是不可变东西),但我会用一句话来概括:

让我们假设你正在写一个游戏,你有一个位于二维飞机上的玩家.例如,Bob在这里:

var player = {
  name: 'Bob',
  favouriteColor: 'moldy mustard',

  x: 4,
  y: 10
};
Run Code Online (Sandbox Code Playgroud)

既然你喝了FP koolaid就想冻结玩家(brrr!希望鲍勃得到一件毛衣):

var player = Object.freeze({
    name: 'Bob',
    ...
});
Run Code Online (Sandbox Code Playgroud)

现在进入游戏循环.在每个滴答声中,玩家的位置都会改变.我们不能只更新播放器对象,因为它已被冻结,因此我们将其复制:

function movePlayer(player, newX, newY) {
    return Object.freeze(Object.assign({}, player, { x: newX, y: newY }));
}
Run Code Online (Sandbox Code Playgroud)

这很好,但是请注意我们正在进行多少无用的复制:在每个tick上,我们创建一个新对象,迭代我们的一个对象,然后在它们之上分配一些新值.在每个刻度上,在每个对象上.那真是一口气.

Immutable为您解决这个问题:

var player = Immutable.Map({
    name: 'Bob',
    ...
});

function movePlayer(player, newX, newY) {
    return player.set('x', newX).set('y', newY);
}
Run Code Online (Sandbox Code Playgroud)

通过持久数据结构的ノ*✧゚魔术✧゚*they,他们承诺尽可能少地进行操作.

思维模式也存在差异.当使用"一个普通的[冻结的] javascript对象"时,所有部分的默认操作都是假设可变性,并且你必须加倍努力才能实现有意义的不变性(也就是说不可变性承认状态存在).这就是freeze存在的原因之一:当你试图做其他事情时,事情会引起恐慌.当然,使用Immutablejs不变性是默认假设,它有一个很好的API.

这并不是说所有的粉红色和玫瑰色的樱桃都在上面.当然,一切都有它的缺点,你不应该因为你可以在任何地方填补Immutable.有时,只是freeze一个物体是足够好的.哎呀,多数认为是时候绰绰有余.它是一个有用的图书馆,它有自己的利基,只是不要被炒作带走.

  • Object.freeze方法的语法语法:Object.freeze({... player,x:newX,y:newY});` (2认同)

eng*_*rce 6

根据我的基准,immutable.js 针对写入操作进行了优化,比Object.assign()更快,但是对于读取操作则较慢。因此,决定权取决于应用程序的类型及其读取/写入比率。以下是基准测试结果的摘要:

-- Mutable
Total elapsed = 103 ms = 50 ms (read) + 53 ms (write).

-- Immutable (Object.assign)
Total elapsed = 2199 ms = 50 ms (read) + 2149 ms (write).

-- Immutable (immutable.js)
Total elapsed = 1690 ms = 638 ms (read) + 1052 ms (write).

-- Immutable (seamless-immutable)
Total elapsed = 91333 ms = 31 ms (read) + 91302 ms (write).

-- Immutable (immutable-assign (created by me))
Total elapsed = 2223 ms = 50 ms (read) + 2173 ms (write).
Run Code Online (Sandbox Code Playgroud)

理想情况下,应该在引入任何性能优化之前对应用程序进行概要分析,但是,不变性是必须及早确定的那些设计决策之一。当您开始使用immutable.js时,您需要在整个应用程序中使用它以获得性能上的好处,因为使用fromJS()和toJS()与普通JS对象进行互操作非常昂贵。

PS:刚发现深度冻结的数组(1000个元素)的更新速度非常慢,大约慢了50倍,因此,仅应在开发模式下使用深度冻结。基准测试结果:

-- Immutable (Object.assign) + deep freeze
Total elapsed = 45903 ms = 96 ms (read) + 45807 ms (write).
Run Code Online (Sandbox Code Playgroud)