Immutable.js的实际案例是什么?

时间:2016-10-08 10:40:22

标签: javascript immutability immutable.js

我理解JS中不变性的好处。但是使用特定的库无法获得任何优势。

在图书馆的主页上有一个很好的“不可变性案例”段落,但对于“Immutable.js的案例”没有明确的答案。

我的意思是要在JS应用程序中实现不变性,你应该保留简单的模式,如Object.prototype.assignArray.prototype.concat,即不要直接改变数据,而是返回一个不接触源的新副本。 / p>

为什么我更喜欢Immutable.List优于原生数组,Immutable.Map优于ES6 Map等等?

这是一个自我约束的问题吗?如果是这样,我应该忘记我的应用程序中的本机数据结构,并仅使用Immutable.js替代?

这是实现更高生产力(在速度和硬件资源方面)的一种开销吗?

它是一种避免错误并降低应用状态复杂性的高级工具吗?

1 个答案:

答案 0 :(得分:7)

  

我的意思是要在JS应用程序中实现不变性,你应该保留简单的模式,如Object.prototype.assignArray.prototype.concat,即不要直接改变数据,而是返回一个不接触源的新副本。 / p>

如果只是那么简单。

包含连接数组的数组



var a = [ [1] ];
var b = [ [2] ];

var c = a.concat(b);

c[0].push(42);

console.log("Array c contains", c);
console.log("Array a contains", a);




包含连接对象的数组



var a = [ { name: "Alice" } ];
var b = [ { name: "Bob" } ];

var c = a.concat(b);

c[0].age = 42;

console.log("Array c is", c);
console.log("Array a is", a);




包含数组和其他对象的对象



var a = { 
  name: "Alice"
}

var foods = { 
  favouriteFoods: [
    "noodles",
    "pancakes"
  ]
};

var seasons = {
  thoughtsOnSeasons: {
    spring: "Beautiful",
    summer: "Too hot",
    autumn: "Pretty",
    winter: "Festive"
  }
};

//this object is now entirely new
var alice = Object.assign({}, a, foods, seasons);

//let's manipulate one of the old objects
foods.favouriteFoods.length = 0;
foods.favouriteFoods.push("carrots");

//let's manipulate one of the properties of the new object
alice.thoughtsOnSeasons.spring = "boring";
alice.thoughtsOnSeasons.summer = "boring";
alice.thoughtsOnSeasons.autumn = "boring";
alice.thoughtsOnSeasons.winter = "boring";

//manipulated through the composed object
console.log(seasons);

//manipulated through the previous object 
console.log(alice);




所以,这实际上是一个非常简单的例子,应该告诉你,你的初始假设是错误的 - 它不是一个简单的模式。如果你的想法是"好的,我将只需编写我自己的函数来执行数组和对象的深度克隆,然后让我们看看另外一件事



var bobby = { name: "Bobby Tables" };
var map = new Map();

map.set("student", bobby);
bobby.name = "Robert'); DROP TABLE Students; --";

console.log(map.get("student"));




如果您仍在思考"没关系,我将拥有自己的地图克隆实用程序",那么您刚刚意识到需要为您克隆属性的东西。

如果你的想法是"我将使用一个可以做到这一点的图书馆"那么你已经为Immutable.js做了一个观点。

但是,这还没有触及不变性,这是Immutable.js提供的主要内容,而不仅仅是一种奇特的克隆实用程序。事实上,通常你不想或不希望消费代码来操纵你的回报。您可以返回包含数组或包含对象的对象的数组,但是如您所见,对它们的任何更改都可能导致对引用数据的更改。结果的改变也可能是不合需要的,并且它就像发生错误一样简单。如果您明确地不希望操作结果,那么您可以返回它的不可变视图。在许多方面,这类似于您确保在接收数据时进行深度克隆,但它只是强制执行该行为,让您知道您是否还没有。

所以,让我试着以相反的顺序回答你的问题

  

它是一种避免错误并降低应用状态复杂性的高级工具吗?

是的,您可以使用它来避免问题和复杂性。这是共享可变数据面临的主要问题,实际上是错误源于意外修改数据和复杂性而导致的错误。

  

这是实现更高生产力(在速度和硬件资源方面)的一种开销吗?

在速度和硬件资源方面 - 几乎没有。可能有一些,但我实际上并没有关于Immutable.js性能的任何数据,但是,我知道不可变数据结构在某些方面可以提高内存效率结构共享。可以附加一个不可变列表,你得到一个新的"但是,在内部列表,列表的开头在实例之间共享,因此可以避免一些GC开销。另一方面,一些其他操作可能需要使用不可变数据结构的更多CPU时间,例如,更改特定索引上的数据。但总的来说,我不会太担心表现。

您从中受益最多的是开发人员的时间和可维护性。

  

这是一个自我约束的问题吗?如果是这样,我应该忘记我的应用程序中的本机数据结构,并仅使用Immutable.js替代?

应该你?这完全是一个完全不同的问题。你没有必要,甚至可能不需要。这取决于您正在进行的项目以及如何进行。完全有可能在一个小项目中使用Immutable.js并获得许多好处。完全可以在没有Immutable.js的情况下处理大型项目而不会受到影响。在某些方面,它是个人选择。我说它对于使用不变性非常有用,因此您可以获得第一手经验。无论你是否需要在任何地方使用它,都无法轻易回答,但你将获得自己评估的方法。