ImmutableJS中的Map()和fromJS()有什么区别?

44
var a = {address: {postcode: 5085}}

var b = Immutable.fromJS(a)
var c = b.setIn(['address', 'suburb'], 'broadview').toJS(); // no error
console.log(c); 

var d = Immutable.Map(a);
var e = d.setIn(['address', 'suburb'], 'broadview').toJS(); // error invalid keyPath(…)

有人能解释一下区别吗?

谢谢。

2个回答

86

在这个例子中,

var a = {address: {postcode: 5085}}
var d = Immutable.Map(a);

在这里,d.get('address')是不可变的。它的值不能更改为任何其他对象。我们只能使用ImmutableJS的Immutable.Map.set()函数从现有对象创建一个新对象。

但是,由d.get('address')引用的对象,即{postcode:5085}是标准的JavaScript对象。它是可变的。像这样的语句可以改变postcode的值:

d.get('address').postcode=6000;

如果你再次检查变量d的值,你会发现它已经发生了改变。

console.log(JSON.stringify(d));   //Outputs {"address":{"postcode":6000}}

这违背了不可变性的原则。

原因在于ImmutableJS数据结构,如ListMap,仅将不可变性特性传递给List/Map的第一层成员。

因此,如果您有数组内部的对象或者对象内部的数组,并且希望它们也是不可变的,您可以选择Immutable.fromJS

var a = {address: {postcode: 5085}}
var b = Immutable.fromJS(a);
b.get('address').postcode=6000;
console.log(JSON.stringify(b));   //Outputs {"address":{"postcode":5085}}

通过上面的示例,您可以清楚地知道fromJS如何使嵌套成员不可变。

我希望您了解了MapfromJS之间的区别。祝一切顺利 =)


2
哇,非常感谢你的解释!我一直在苦苦挣扎,现在终于明白为什么我的 map.get(k) 返回的是引用(以及如何避免不得不进行某种愚蠢的 deepCopy(map.get(k)))。 - grendian
太好了!Immutable.js Map文档并没有清楚地说明与fromJS的核心区别:https://facebook.github.io/immutable-js/docs/#/Map - Tom McKenzie

25

fromJS 进行深度转换。也就是说,它将递归遍历所有键并将所有元素转换为列表、映射等。

在您的第二个示例中,address 是一个普通对象,而不是 ImmutableJS 对象,因此您不能使用 setIn 更改其值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接