在Object.assign或spread运算符

时间:2016-08-30 12:41:37

标签: javascript reactjs redux immutability

到目前为止,大多数“起动器锅炉”和一些关于react / redux的帖子我都看到鼓励使用immutable.js来解决可变性问题。我个人依赖Object.assign或传播运算符来处理这个问题,因此在immutable.js中并没有真正看到优势,因为它增加了额外的学习,并且从用于可变性的vanilla js技术转移了一些。我试图找到切换的正当理由,但我无法在此问这里,看看它为何如此受欢迎。

6 个答案:

答案 0 :(得分:30)

这完全取决于效率。

持久性数据结构

持久数据结构通过始终产生新的数据结构来保持其自身的先前版本。为了避免昂贵的克隆,仅存储与先前数据结构的差异,而在它们之间共享交集。这种策略称为结构共享。因此,持久数据结构比使用Object.assign或扩展运算符进行克隆要高效得多。

Javascript

中持久性数据结构的缺点

不幸的是,Javascript本身并不支持持久数据结构。这就是immutable.js存在的原因,它的对象与普通的旧Javascript Object有很大的不同。这导致更冗长的代码和持久数据结构对本机Javascript数据结构的大量转换。

关键问题

immutable.js的结构共享(效率)的好处何时超过其缺点(详细程度,转换次数)?

我认为只有在拥有众多广泛的对象和集合的大型项目中,当克隆整个数据结构和垃圾收集变得更加昂贵时,图书馆才能获得回报。

答案 1 :(得分:14)

I have created the performance benchmarks for multiple immutable libraries, the script and results are located inside the immutable-assign (GitHub project),这表明immutable.js针对写入操作进行了优化,比但是,Object.assign()对于读取操作来说速度较慢。以下是基准测试结果的摘要:

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

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

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

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

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

因此,是否使用immutable.js将取决于应用程序的类型及其读写比率。如果你有很多写操作,那么immutable.js将是一个不错的选择。

  

Premature optimization is the root of all evil

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

答案 2 :(得分:3)

我认为ImmutableJs的主要优势在于其数据结构和速度。当然,它也强制执行不变性,但无论如何你应该这样做,这只是一个额外的好处。

例如,假设您的reducer中有一个非常大的对象,并且您想要更改该对象的一小部分。由于不变性,您无法直接更改对象,但必须创建对象的副本。你可以通过复制所有内容(使用扩展运算符在ES6中)。

那么问题是什么?复制非常大的对象非常慢。 ImmutableJS中的数据结构执行称为结构共享的操作,您实际上只需要更改所需的数据。您未更改的其他数据在对象之间共享,因此不会被复制。

这样做的结果是高效的数据结构,快速写入。

ImmutableJS还为深层对象提供了简单的比较。例如

const a = Immutable.Map({ a: Immutable.Map({ a: 'a', b: 'b'}), b: 'b'});
const b = Immutable.Map({ a: Immutable.Map({ a: 'a', b: 'b'}), b: 'b'});

console.log(a.equals(b)) // true 

如果没有这个,你需要某种深度比较功能,这也需要花费很多时间,而这里的根节点包含整个数据结构的哈希(不要引用我这个,这是怎么回事我记得它,但比较总是即时的),所以比较总是O(1)即即时,无论对象大小。

这在React shouldComponentUpdate方法中尤其有用,您可以使用此equals函数比较道具,该函数即时运行。

当然,也有缺点,如果你混合使用immutablejs结构和常规对象,很难说出它是什么。您的代码库也充斥着immutableJS语法,这与常规Javascript不同。

另一个缺点是,如果你不打算使用深度嵌套的对象,它会比普通的旧js慢一些,因为数据结构确实有一些开销。

只需2美分。

答案 3 :(得分:2)

immutable.js的优点在于它强制执行一个不可变的redux存储(你可能忘记扩展,或者做一个草率的工作来保护你的商店免受修改)和简化Object.assign或点差运算符相比减少器很多(顺便说一下,两者都很浅!)。

话虽如此,我在一个大的Angular 1.x项目中使用了redux + immutable并且存在缺点:性能问题,不清楚什么是不可变的,什么不是,Angular不能在{{中使用immutable.js结构但是,不确定React,会喜欢听到意见。

答案 4 :(得分:1)

immutable.js为您提供了许多始终返回新对象的实用程序。

示例:

var Immutable = require('immutable');
var map1 = Immutable.Map({a:1, b:2, c:3});
var map2 = map1.set('b', 50);
map1.get('b'); // 2
map2.get('b'); // 50

对于just react / redux我个人认为Object.assign是强大的,但在某些情况下,使用该库可以为您节省几行代码。

答案 5 :(得分:1)

不仅仅是通过持久数据结构获得性能提升。不可变性本身就是非常理想的质量,因为它完全消除了由意外突变引起的任何错误。另外,在Javascript中使用方便的API获得理智的数据结构是很好的,实际上可以使用的东西,并且即使最近添加了ES6和ES7,immutable.js也领先于vanillla对象和数组。它就像jQuery一样 - 它非常受欢迎,因为与vanilla DOM API(这只是一场噩梦)相比,它的API真的很棒且易于使用。当然,你可以尝试使用vanilla对象保持不变,但是你不必忘记Object.assign和数组传播每一个时间,并且使用immutable.js你根本不会出错,这里的任何突变都是明确的