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

这可能是由于我不熟悉javascript而引起的,因为我是该语言的新手,但到目前为止,我还没有找到可行的解决方案。

问题是我要创建一个对象数组的副本数组,然后在不更改初始数组中对象值的情况下更改副本数组中的数据,最后再次将副本数组分配给初始数组,因此我可以在具有初始值的另一个函数中再次使用它。

我编写了一个简单的程序,其中包含两个类-拥有一些属性的国家(地区)和更改其中一个属性的函数,以及拥有国家(地区)数组的世界(World)和改变数组中所有国家/地区的数据的函数。我创建一个World实例,调用changeAllCountriesData函数 最后,输出countrys数组和copyData数组的值。如您所见,它们都已更改,我不确定原因。

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);

我尝试用其他方法代替this.copyData = this.countries.slice(0):

1。

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

2。

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

3。

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

上面的一个在每次计算后返回NaN。

4。

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

5,

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

这些方法都没有以这样的一种方式制作副本数组,即初始副本保持不变或在不返回NaN的情况下进行计算。

评论
  • laut
    laut 回复

    In JS, objects are copied using reference. So when you so .slice(0) you are partially correct but the issue is, internal values are objects. 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. 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.

    尝试更新到

    cloneObject() {
      const {name, area, population} = this;
      return new Country(name, area, population)
    }
    
    ...
    
    this.copyData = this.countries.map( (obj) => obj.cloneObject() );
    

    注意:

    样例代码:

    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);