在不可变JS中更新列表中的对象

Updating objects in List in ImmutableJS

本文关键字:对象 列表 更新 JS 不可变      更新时间:2023-09-26

在使用对象数组时,我对ImmutableJS的功能有点困惑。下面的示例表明,即使 List x 是不可变的,我仍然可以在不使用不可变列表的 update() 函数的情况下修改列表中对象的属性。

我的问题是,如果我仍然可以修改对象的内容,为什么还要使用不可变?我希望这个模块能保护我免受这种情况的影响。我意识到我将无法在列表中添加或删除整个对象,但这并不能完全保护我修改列表,在处理 React 状态的列表时,我不希望能够这样做。

我注意到的另一件有趣的事情是,当我在第一次执行更新后直接修改名称时,x.get(0).name 和 y.get(0).name 都发生了变化。我认为来自 update() 的结果列表不会包含对列表中相同对象的引用。

在这种情况下,不可变JS如何以及为什么真正帮助我?

var x = Immutable.List.of({name: 'foo'});
console.log(x.get(0).name);
var y = x.update(0, (element) => {
  element.name = 'bar';
  return element;
});
console.log(x.get(0).name);
console.log(y.get(0).name);
x.get(0).name = 'baz';
console.log(x.get(0).name);
console.log(y.get(0).name);
Output:
foo
bar
bar
baz
baz

https://jsfiddle.net/shotolab/rwh116uw/1/

@SpiderPig建议使用 Map 的示例:

var x = Immutable.List.of(new Immutable.Map({name: 'foo'}));
console.log(x.get(0).get('name'));
var y = x.update(0, (element) => {
  return element.set('name', 'bar');
});
console.log(x.get(0).get('name'));
console.log(y.get(0).get('name'));
Output:
foo
foo
bar

虽然最后一个示例显示了我想要完成的目标,但最终我不知道我最终是否会使用 Map 或 List 甚至 ImmutableJS。我不喜欢的是备用 API(尤其是对于映射对象)。我担心当我将我的项目交给另一个开发人员时,或者当其他人加入团队时,正确使用这些不可变的对象和列表将完全崩溃,而没有适当的治理。

也许这更像是对 React 的评论,但如果 React 打算让状态是不可变的,但它没有被强制执行,在我看来,这最终会在一个与多个开发人员快速发展的项目中造成混乱。我尽力不改变状态,但忘记了修改列表/数组中的对象很容易犯错误。

> 不可变.js不提供真正的不可变性,因为您无法直接修改对象 - 它只是提供 API 来帮助您维护不可变状态。

update -函数应返回索引对象的全新版本:

var y = x.update(0, (element) => {
  return { name : "bar"};
});

但做这样的事情是一个很大的禁忌:x.get(0).name = 'baz';

这是对整个事情的解释比我所能写的要好得多:https://github.com/facebook/immutable-js/issues/481

不可变.js的目的是允许重用未修改的对象,这消耗更少的内存并提供良好的实际性能。

还有库"无缝不可变",它冻结对象,使它们无法修改,但这在JavaScript下会带来一些性能损失:https://github.com/rtfeldman/seamless-immutable