简体   繁体   English

有没有办法复制 javascript 中的对象数组?

[英]Is there a way to copy an array of objects in javascript?

This may be an issue caused by my incompetence in javascript as I am new to the language but so far I haven't found a working solution.这可能是我在 javascript 中的无能造成的问题,因为我是该语言的新手,但到目前为止我还没有找到有效的解决方案。

The problem is that I want to make a copy array of an array of objects, then change the data in the copy array without changing the values of the objects in the initial array and finally assign the copy array to the initial array again so I can use it again in another function with the initial values.问题是我想制作一个对象数组的副本数组,然后在不更改初始数组中对象的值的情况下更改副本数组中的数据,最后再次将副本数组分配给初始数组,这样我就可以使用初始值在另一个 function 中再次使用它。

I have made a simple program containing two classes - Country which holds some properties and a function to change one of these properties and World which hold an array of countries and a function to change the data of all countries in the array.我制作了一个包含两个类的简单程序 - Country 包含一些属性和一个 function 来更改其中一个属性,World 包含一个国家数组和一个 function 来更改数组中所有国家的数据。 I create a World instance, call the changeAllCountriesData function and at the end print the values of both the countries array and the copyData array.我创建了一个 World 实例,调用 changeAllCountriesData function 并在最后打印 countries 数组和 copyData 数组的值。 As you can see they have both changed and I am unsure of the reason why.如您所见,它们都发生了变化,我不确定原因。

 class Country{ name; area; population; constructor(name, area, population){ this.name = name; this.area = area; this.population = population; } changeData(){ this.population += Math.round(this.population * 0.02); } } class World{ countries = []; copyData = []; constructor(){ this.loadData(); this.copyData = this.countries.slice(0); } loadData(){ this.countries.push(new Country("Denmark", 41990, 5839809)); this.countries.push(new Country("Germany", 349360, 83159604)); this.countries.push(new Country("Netherlands", 33690, 17342709)); } changeAllCountriesData(){ this.copyData.forEach(c => { c.changeData(); }) } } console.log("Initial information for the population: 5839809, 83159604, 17342709") w = new World(); w.changeAllCountriesData(); console.log("countries array:") console.log(w.countries); console.log("copyData array:") console.log(w.copyData);

Other ways I have tried instead of this.copyData = this.countries.slice(0):我尝试过的其他方法代替了 this.copyData = this.countries.slice(0):

1. 1.

this.copyData = [...this.countries]

2. 2.

this.copyArray = Array.from(this.countries);
this.copyData = copyArray[0];

3. 3.

this.countries.forEach(c => {
      this.copyData.push({...c});
})

The one above returns NaN after each calculation.上面的那个在每次计算后返回 NaN。

4. 4.

this.countries.forEach(c => {
      let obj = Object.assign({}, c);
      this.copyData.push(obj);
})

5. 5.

this.copyData = this.countries.concat();

None of these methods has made a copy array in such a way that the initial one remains unchanged or the calculations are made without returning NaN.这些方法都没有以初始数组保持不变或在不返回 NaN 的情况下进行计算的方式制作副本数组。

In JS, objects are copied using reference.在 JS 中,对象是使用引用来复制的。 So when you so .slice(0) you are partially correct but the issue is, internal values are objects.因此,当您.slice(0)时,您是部分正确的,但问题是,内部值是对象。 So the new array has previous values.所以新数组有以前的值。

Now you can also try .map(obj => ({...obj }) ) but this will not work as object spread will create a new object with properties but not methods.现在您也可以尝试.map(obj => ({...obj }) )但这将不起作用,因为 object spread 将创建一个新的 object,它具有属性而不是方法。 So any method, like changeData will not be there on this object. Due to this, you will have to create a copy mechanism to your class.所以任何方法,比如changeData都不会出现在这个 object 上。因此,你必须创建一个复制机制到你的 class。

Try updating to尝试更新到

cloneObject() {
  const {name, area, population} = this;
  return new Country(name, area, population)
}

...

this.copyData = this.countries.map( (obj) => obj.cloneObject() );

Note: You can extend this function's capability.注意:您可以扩展此功能的功能。 You can add an argument to override the values.您可以添加一个参数来覆盖这些值。 That will allow you to do multiple operations in one go:这将允许您在一个 go 中执行多项操作:

cloneObject( overrides ) {
  const { name, area, population } = { ...this, ...overrides };
  return new Country(name, area, population)
}

...

this.copyData = this.countries.map( (obj) => obj.cloneObject({ name: 'Hello World' }) );

Sample Code:示例代码:

 class Country{ name; area; population; constructor(name, area, population){ this.name = name; this.area = area; this.population = population; } cloneObject() { const {name, area, population} = this; return new Country(name, area, population) } changeData(){ this.population += Math.round(this.population * 0.02); } } class World{ countries = []; copyData = []; constructor(){ this.loadData(); this.copyData = this.countries.map( (obj) => obj.cloneObject() ); } loadData(){ this.countries.push(new Country("Denmark", 41990, 5839809)); this.countries.push(new Country("Germany", 349360, 83159604)); this.countries.push(new Country("Netherlands", 33690, 17342709)); } changeAllCountriesData(){ this.copyData.forEach(c => { c.changeData(); }) } } console.log("Initial information for the population: 5839809, 83159604, 17342709") w = new World(); w.changeAllCountriesData(); console.log("countries array:") console.log(w.countries); console.log("copyData array:") console.log(w.copyData);

I was about to comment, but could not as I dont have enough points yet.我正要发表评论,但不能,因为我还没有足够的分数。

  1. In changeAllCountriesData() (inside class World ) you are trying to invoke changeDate() function which is a local function inside class Country.changeAllCountriesData() (在class World内)中,您正在尝试调用changeDate() function,这是 class Country 内的本地 function。 I'm not sure class World can access local function of another class directly.我不确定 class World 是否可以直接访问另一个 class 的本地 function。 You can invoke function inside a class after you assigned a class into a variable var , let or const .在将 class 分配给变量varletconst之后,您可以在 class 中调用 function 。 Example:例子:

    const codeland = new Country('USA', 123, 456); const codeland = new Country('美国', 123, 456);

    codeland.changeData(); codeland.changeData();

Now, codeland is global variable.现在,codeland 是全局变量。 Now you can access changeData() function via codeland variable in your class World.现在您可以通过 class 世界中的 codeland 变量访问 changeData() function。

I'm not pro at JavaScript, and there must be simpler way, I believe!我不是 JavaScript 的专家,我相信一定有更简单的方法!

As for copying arrays, method #1 and #3 are correct.至于复制arrays,方法#1和#3是正确的。 (Not sure about method #2 and #4. Method #5 concatenated countries to copyData .) They return NaN, because both countries and copyData are empty while you are copying data from one array to another. (不确定方法 #2 和 #4。方法 #5 将countries连接到copyData 。)它们返回 NaN,因为当您将数据从一个数组复制到另一个数组时,国家和 copyData 都是空的。 Therefore, it is NaN (or undefined).因此,它是 NaN(或未定义)。

I hope it helps!我希望它有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM