JavaScript解决方案

ES6中添加了一些新功能,允许更容易实现不可变数据模式。

Object.assign

Object.assign允许我们将一个对象的属性合并到另一个对象,用匹配的名称替换属性的值。我们可以使用它来复制对象的值,而不改变现有的值。

let movie1 = {
  name: 'Star Wars',
  episode: 7
};
let movie2 = Object.assign({}, movie1);
movie2.episode = 8;
console.log(movie1.episode); // writes 7
console.log(movie2.episode); // writes 8

你可以看到,虽然我们有一些复制对象的方法,但是我们没有使它不可变,因为我们可以将episode的属性设置为8.另外,在这种情况下我们如何修改episode属性? 我们通过调用assign:

let movie1 = {
  name: 'Star Wars',
  episode: 7
};
let movie2 = Object.assign({}, movie1, { episode: 8 });
console.log(movie1.episode); // writes 7
console.log(movie2.episode); // writes 8

Object.freeze

Object.freeze允许我们禁用对象变动。

let movie1 = {
  name: 'Star Wars',
  episode: 7
};
let movie2 = Object.freeze(Object.assign({}, movie1));
movie2.episode = 8; // fails silently in non-strict mode,
                    // throws error in strict mode
console.log(movie1.episode); // writes 7
console.log(movie2.episode); // writes 7

然而,这种模式的一个问题是,我们的代码会很冗长并且理解我们的数据实际上发生了什么会很困难,以及使用Object.freezeObject.assign会对所有的样板进行调用和读取。 我们需要一些更明智的接口来创建不可变数据和与其交互,这就是适用Immutable.js的地方。

Object.freeze很慢,不应该与大数组一起使用。

下一节:为了解决我们的可变性问题,Immutable.js必须提供两个核心可变类型(Object和Array)的不可变版本。