什么是深度不可变性?

4
阅读Promises/A+规范时,我遇到了“深度不可变性”这个术语。文本如下:

这里,“不得更改”表示不可变的标识(即===),但并不意味着具有深度的不可变性。

什么是深度不可变性?能否举个例子解释一下?


你需要沿着 === 的工作方式和它用于确定两个东西是否相等的方法思考。 - Bartek Banachewicz
1
或者看一下 const 如何工作。const 值具有不可变的身份,但不是深度不可变的。 - tex
2个回答

6

一旦一个Promise被解决,任何试图再次解决它的尝试都将无效,这意味着已经解决的值将始终与原始解决的值严格相等。然而,这并不意味着该值不能更改,即“不意味着具有深度不可变性”。

可以通过以下示例进行演示:

var value = [1];
var p = Promise.resolve(value);
p.then(a => console.log(a));                  // [1]
p.then(a => console.log(a === value));        // true

p.then(a => { a = [2]; console.log(a);});     // [2]
p.then(a => console.log(a));                  // [1]

p.then(a => { a[0] = 2; console.log(a);});    // [2]
p.then(a => console.log(a));                  // [2]
p.then(a => console.log(a === value));        // true

如您所见,从已解决的 Promise 返回的值始终保持相同的对象值 - a === value。试图将对象绑定到不同的值只会在 then 块的范围内应用,我们在下一次调用 Promise 的 then 方法时仍然看到原始的对象值。

当我们更改此数组属性之一(在本例中为第一个元素)的值时,我们注意到此更改会影响原始值,因此也会影响从此 Promise 返回的已解决值。如果已解决的值具有深度不可变性,则其所有属性及其属性都将是不可变的,但我们刚刚证明这并非事实。


非常好的答案和非常有用的示例!您能解释一下这段话吗:“一旦承诺已经被解决,任何试图再次解决它的尝试都将无效”?对我来说,这听起来可能与深度不可变性无关,而实际上是 Promises/A+ 规范的另一部分。但也许我误解了? - BillyBBone
这就解释了为什么你总是会从 Promise 中收到原始的 Object 值,因为它不能被解析为另一个值,也解释了为什么他们使用“不得更改”的术语。这种措辞可能会被误解为深度不可变性,这就是它的关系以及规范澄清它不是这样的原因。 - Joel

2
在面向对象的语言中,没有一种很好的方法来锁定对象属性。例如,如果你的应用程序中有多个对象实例,并且你在其中一个引用上更改了属性值,那么该对象至少就是在引用之间存在数据差异。深不变性确保该对象的数据在所有引用中始终按照编程规范被锁定。
如果应用程序规范规定具有深度不可变性,则更改对象或重新分配其字段都是非法的。 如果应用程序规定具有浅不变性,则仍然不能重新分配对象字段,因此它是不可变的,但是允许更改对象引用。
在这里有一篇非常好的文章:https://homes.cs.washington.edu/~mernst/pubs/immutability-aliasing-2013-lncs7850.pdf 根据文章,大多数客户端都喜欢深度不可变性。

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