【发布时间】:2015-11-07 15:57:17
【问题描述】:
到目前为止,Javascript 中的不变性似乎有两种相反的解决方案:
- immutable.js
- 无缝不可变
immutable.js 引入了他们自己的(浅显的)不可变对象,这些对象与对象和数组的默认 javascript 协议不兼容。
seamless-immutable 使用完全不可变的 POJO,没有任何魔法,但没有结构共享。
将两全其美的优点结合起来会很棒。不可变的原型链/树会是一个合适的解决方案吗?
底层原型机制带来希望:
var a = [1, 2, 3];
var b = Object.create(a);
b[0]; // 1
b.map(function (x) { return ++x; }); // 2, 3, 4
b.push(4, 5, 6); // initial assignment of b
a; // 1, 2, 3
b; // 1, 2, 3, 4, 5, 6
for (var i = 0; i < b.length; i++) {
console.log(b[i]);
} // 1, 2, 3, 4, 5, 6
a[1] = null; // prototype mutation
a; // 1, null, 3
b; // 1, null, 3, 4, 5, 6
b.unshift(0); // instance mutation
a; // 1, null, 3
b; // 0, 1, null, 3, 4, 5, 6 !!!
当当前实例 (b) 的突变(未移位)使其原型无法提供它们的值时,js 引擎似乎会自动将这些值直接复制到实例中。我不知道,但这完全有道理。
但是,使用不可变(键控/索引)对象很快就会遇到问题:
var a = [1, 2, 3];
Object.freeze(a);
var b = Object.create(a);
b.push(4, 5, 6); // Error: Cannot assign to read only property "length"
Object.freeze(b);
这个很简单:length 属性继承自不可变原型,因此不可变。解决问题并不难:
var b = Object.create(a, {length: {value: a.length, writable: true}});
但可能还会有其他问题,尤其是在更复杂的现实世界场景中。
也许有人已经处理过这个想法并且可以告诉我,是否值得对此进行推理。
Aadit 对一个相关问题的answer 和Bergi 对此的评论触及了我的问题而没有给出答案。
【问题讨论】:
-
我觉得这将是一个真正有趣的讨论,但对于 Stack Overflow 来说,这种讨论并不完全正确(更适用于特定问题)。一旦你达到 20 次代表,你就应该来chat 与我们讨论。
-
是的,我不想在那边与 Aadit 进行讨论,但我很高兴在这里提供答案。并希望@AaditMShah 可以给出一些对位,我想学习一些新的东西:-)
标签: javascript prototype immutability prototypal-inheritance immutable.js