TypeScript:修改字典列表的副本而不进行突变

TypeScript: Modifying copy of list of dictionary without mutation

我已经看了几个答案,我认为这可能是一个逻辑错误,但我无法想出一种方法来实现这一点。

我必须列出 typescript/javascript 中的词典。一个是另一个用于跟踪的副本。当我修改其中一个列表时,另一个列表也会被修改。请解释实现相同目标的可能方法

  var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
//
  var b = a.slice();
//I have tried different ways of slicing as well; for example: b = [...a]
b.filter(i=> i['x']= i['x'].filter(z=>z%2==0))
console.log(a,b)

此代码同时修改列表 a 和 b。我想在不影响a的情况下实现b的修改,可以吗?

你可以试试这个:

var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
var b = JSON.parse(JSON.stringify(a));

b.filter(i=> i['x']= i['x'].filter(z=>z%2==0))
console.log(a,b)

您需要对源进行深拷贝

创建深拷贝的方法有多种:例如检查这个

一种简单的方法是转换为 JSON 并返回

var b = JSON.parse(JSON.stringify(a));

var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})

var b = JSON.parse(JSON.stringify(a));

//I have tried different ways of slicing as well; for example: b = [...a]
b.filter(i=> i['x']= i['x'].filter(z=>z%2==0))
console.log(a, b)

发生这种情况是因为对象 {"x":[2,3,14,5,7,8],"y":[7,8,9,10]} 实际上在您的代码中只存在一次。这个特定对象存在于两个不同的数组中。这意味着当您编辑此对象时,更改将反映在两个数组中。

您可以通过 a[0] === b[0] 来验证这一点。这导致 true,因为对该对象的引用是相同的:它们实际上是同一个对象,而不是恰好包含完全相同数据的两个对象。

这个问题有两种常见的解决方法:

对于这种特殊情况,深拷贝是最简单的解决方案。这将重新创建数组,即使数据看起来相同,但它们实际上是不同的对象。最简单的方法是使用 var b = JSON.parse(JSON.stringify(a))。请记住,这可能并不总是有效,因为圆形结构会导致错误并且功能会丢失。

第二种方法是以不可变的方式工作,即。创建新对象而不是修改现有对象。有很多库可以帮助解决这个问题,例如 'immutability-helper' 或 'immutable.js'。你也可以在没有库的情况下解决这个问题,但有时它会导致代码难看。例子

var b = a.map(obj => ({ ...obj, x: obj.x.filter(numbers => numbers % 2 === 0)}))

我们创建包含我们想要的值的新对象和数组,而不是将其变异为我们想要的值。 ...obj 给我们一个对象的浅表副本,然后我们用过滤后的数据用一个全新的数组(即未突变)替换 x 属性。