javascript - 使用 javascript 原型(prototype)系统创建共享结构的不可变对象(immutable对象)是否有意义

标签 javascript prototype immutability prototypal-inheritance immutable.js

到目前为止,对于 Javascript 中的不变性似乎有两种相反的解决方案:

  • 不可变的.js
  • 无缝不可变

immutable.js 引入了自己的(浅层)不可变对象(immutable对象),这些对象与对象和数组的默认 javascript 协议(protocol)不兼容。

seamless-immutable 使用完全不可变的 POJO,没有任何魔法,但没有结构共享。

将两全其美结合起来会很棒。不可变原型(prototype)链/树能否成为合适的解决方案?

底层原型(prototype)机制给了希望:

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) 的突变(取消移位)使其原型(prototype)无法提供它们的值时,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 属性继承自不可变原型(prototype),因此不可变。解决问题并不难:

var b = Object.create(a, {length: {value: a.length, writable: true}});

但可能还会有其他问题,尤其是在更复杂的现实世界场景中。

也许有人已经处理过这个想法并且可以告诉我,是否值得对其进行推理。

阿迪特的 answer对相关问题和 Bergi 的评论触及我的问题而没有给出答案。

最佳答案

the js engine seems to copy these values straight into the instance automatically

那是因为所有数组方法(shiftpush 等)都只使用对索引的赋值(幸运的是,对 .length,这不会在非数组上自动更新)。如您所知,赋值只是在继承对象上创建一个新属性,即使原型(prototype)具有该属性(除非它具有奇怪的属性,如您的卡住长度示例)。

无论如何,您的实际问题是

Could immutable prototype chains/trees be a proper solution?

。问题是原型(prototype)链永远不会被垃圾回收。一旦所有继承的属性都被新的“变异”实例覆盖,引擎就不知道您“不再需要”原型(prototype)了——并永远保留它。
您需要手动对其进行垃圾收集(取消引用),这正是具有结构共享的 immutable.js 所做的。只有那个mutating the [[prototype]] is a bad idea ,因此您可以通过其他方式更好地管理您的结构并手动进行属性查找。

关于javascript - 使用 javascript 原型(prototype)系统创建共享结构的不可变对象(immutable对象)是否有意义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33584671/

相关文章:

javascript - 在 for 循环中生成一个 unicode 字符列表

javascript - 已发布使用 JavaScript 将 PHP 数据加载到 HTML 文件的问题

javascript - 如何在 HTML 中显示此代码?

javascript - 如何在 javascript 函数对象中测试是否调用了无效方法?

arrays - 修改字典中的 Swift 数组<String, AnyObject>

javascript - 从嵌套对象中删除数据而不改变

javascript - 如何正确检查 Set 是否为空

javascript - 用 object.create 定义的原型(prototype)的构造函数属性从哪里来?

Javascript - Object.create 为什么将函数作为参数?

java - 从类(class)收集信息的适当方式/模式是什么?