在 ImmutableJS 中更新列表中的对象
Updating objects in List in ImmutableJS
在处理对象数组时,我对 ImmutableJS 的功能感到有点困惑。下面的示例表明,即使列表 x 是不可变的,我仍然可以在使用和不使用不可变列表的 update() 函数的情况下修改列表内对象的属性。
我的问题是,如果我仍然可以修改对象的内容,为什么还要使用 Immutable?我希望这个模块能保护我免受这种伤害。我意识到我将无法添加或删除整个对象 to/from 列表,但这并不能完全保护我免于修改列表,在 React 状态下处理列表时,我不想能做到。
我注意到的另一个有趣的事情是,当我在第一次执行更新后直接修改名称时,x.get(0).name 和 y.get(0).name 都被更改了。我认为 update() 的结果列表不会包含对列表中相同对象的引用。
在这种情况下,ImmutableJS 如何以及为何真正帮助我?
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 打算让状态不可变,但它没有强制执行,在我看来这将在一个快速发展的项目中结束一团糟与多个开发人员。我尽力不改变状态,但忘记了修改 list/array 中的对象是很容易犯的错误。
从您无法直接修改对象的意义上说,immutable.js 不提供真正的不可变性 - 它只是提供 API 来帮助您保持不可变状态。
update 函数应该 return 索引对象的全新版本:
var y = x.update(0, (element) => {
return { name : "bar"};
});
但是做这样的事情是一个很大的禁忌:x.get(0).name = 'baz';
这是对整个事情的一个比我写的更好的解释:
https://github.com/facebook/immutable-js/issues/481
immutable.js的要点是允许重用未修改的对象,这样消耗内存少,实用性能好。
还有库 "Seamless immutable",它冻结了对象,所以它们不能被修改,但是在 JavaScript 下这会带来一些性能损失:https://github.com/rtfeldman/seamless-immutable
在处理对象数组时,我对 ImmutableJS 的功能感到有点困惑。下面的示例表明,即使列表 x 是不可变的,我仍然可以在使用和不使用不可变列表的 update() 函数的情况下修改列表内对象的属性。
我的问题是,如果我仍然可以修改对象的内容,为什么还要使用 Immutable?我希望这个模块能保护我免受这种伤害。我意识到我将无法添加或删除整个对象 to/from 列表,但这并不能完全保护我免于修改列表,在 React 状态下处理列表时,我不想能做到。
我注意到的另一个有趣的事情是,当我在第一次执行更新后直接修改名称时,x.get(0).name 和 y.get(0).name 都被更改了。我认为 update() 的结果列表不会包含对列表中相同对象的引用。
在这种情况下,ImmutableJS 如何以及为何真正帮助我?
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 打算让状态不可变,但它没有强制执行,在我看来这将在一个快速发展的项目中结束一团糟与多个开发人员。我尽力不改变状态,但忘记了修改 list/array 中的对象是很容易犯的错误。
从您无法直接修改对象的意义上说,immutable.js 不提供真正的不可变性 - 它只是提供 API 来帮助您保持不可变状态。
update 函数应该 return 索引对象的全新版本:
var y = x.update(0, (element) => {
return { name : "bar"};
});
但是做这样的事情是一个很大的禁忌:x.get(0).name = 'baz';
这是对整个事情的一个比我写的更好的解释: https://github.com/facebook/immutable-js/issues/481
immutable.js的要点是允许重用未修改的对象,这样消耗内存少,实用性能好。
还有库 "Seamless immutable",它冻结了对象,所以它们不能被修改,但是在 JavaScript 下这会带来一些性能损失:https://github.com/rtfeldman/seamless-immutable