Immutable.js的实际情况是什么?

What is the practical case of the Immutable.js?

本文关键字:是什么 实际情况 js Immutable      更新时间:2023-09-26

我理解JS中不变性的好处。但是不能得到使用特定库的任何好处。

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

我的意思是在JS应用程序中实现不变性,你应该只保持简单的模式,如Object.prototype.assign, Array.prototype.concat,即不直接改变数据,但返回一个新的副本不触及源。

为什么我应该更喜欢Immutable.List而不是本机阵列,Immutable.Map而不是ES6 Map等等?

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

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

是一个先进的工具,以避免错误和减少应用程序状态的复杂性?

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

要是有那么简单就好了。

包含正在连接的数组的数组

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的大型项目中工作而不受其影响是完全可能的。在某种程度上,这是个人的选择。我想说,使用不变性绝对是有用的,这样你就可以获得第一手的经验。你是否需要在任何地方使用它,真的不容易回答,但你将获得自己评估的方法。