2016-03-21 83 views
1

使用對象數組時,我對ImmutableJS的功能有點困惑。下面的例子顯示,即使List x是不可變的,我仍然可以使用Immutable List的update()函數修改列表中的對象的屬性。在ImmutableJS中更新列表中的對象

我的問題是,如果我仍然可以修改我的對象的內容,爲什麼我會使用Immutable?我期望這個模塊能夠保護我。我意識到我無法在列表中添加或刪除整個對象,但這並不能完全保護我無法修改列表,當使用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 
@ SpiderPig的使用地圖的建議的

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

例子:

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打算讓國家變得不可改變,但它並沒有被強制執行,在我看來,這樣做最終會導致一個混亂,多個開發者。我盡我所能不要改變狀態,但忘記修改列表/數組中的對象是非常容易犯的錯誤。

+1

只有列表本身是不可變的。裏面的物體不是。您可以將不可變元素放入列表中,例如使用Immutable.Map而不是普通的JS對象。 – SpiderPig

+0

我添加了一個結合使用Map和List的建議示例。這最終實現了我之後的工作,但是需要一個不同的API來修改Mapped對象,而不僅僅是一個普通的JS對象。 –

回答

2

immutable.js並不提供真正的不可變性,因爲您無法直接修改對象 - 它僅提供可幫助您維護不可變狀態的API。

更新 - 函數應該返回索引對象的完全新版本:

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

但是做這樣的事情,這是一個很大的禁忌:x.get(0).name = 'baz';

這裏的一個更好的解釋整個事情比我所能寫: https://github.com/facebook/immutable-js/issues/481

immutable.js的要點是允許重複使用對象的哪些不是修改後,消耗更少的內存並提供良好的實際性能。

還有圖書館「無縫不可改變的」,其凍結的對象,使他們不能修改,但這種帶有下的JavaScript的性能損失:https://github.com/rtfeldman/seamless-immutable

+0

感謝您提供問題481的鏈接。並且您的回答證實,至少我遇到的行爲是預期的行爲。 –