如何在Javascript中使用数组成员深度复制(克隆)对象?

时间:2015-07-15 15:45:36

标签: javascript arrays object clone deep-copy

简介

我有一个Persons类,其中包含Person数组和函数:

function Persons() {
  this.mItems = []; // Array of Objects Person
}

Persons.prototype = {
  calculateScores : function() {
    // Do some stuff
  }
}

班级Person有成员和职能:

function Person(name) {
  this.name = name; // Name of the Person
  this.score = 0;
}

Person.prototype = {
  calculateScore : function() {
    // Do some stuff
  }
}

我希望程序执行以下操作:

var persons = new Persons();
var person0 = new Person("John");
var person1 = new Person("Sam");
persons.mItems.push(person0);
persons.mItems.push(person1);

// Completely clone the original Objects
clonedPersons = persons.clone(); // I am looking for a clone() function

// Modify an item in the cloned Objects
clonedPersons.mItems[0].name = "Mick";

// Check that the original Objects have not been modified
console.log(persons.mItems[0].name); // John : Not modified
console.log(clonedPersons.mItems[0].name); // Mick

问题

我想深度复制Persons 的实例,以完全复制Person的数组。必须复制对象人员。必须保留对象的功能。

JQuery.extend()

JQuery.extend(true, {}, persons)克隆Persons的直接成员,但浅层复制Person个对象。

console.log(persons.mItems[0].name); // Mick : Where is John ?!
console.log(clonedPersons.mItems[0].name); // Mick

JSON.parse(json.stringify())

clonedPersons = JSON.parse(json.stringify(persons))克隆对象,但删除了这些函数。

persons.mItems[0].calculateScore(); // Does not exists !!!

感谢您的回答。

2 个答案:

答案 0 :(得分:3)

如果您正在处理自定义类,那么您将需要实现自定义clone方法。通常,在这种情况下,我有2个单独的clone函数,一个在Person模型上,另一个在Persons集合上。

Persons.prototype = {
  clone: function() {
    var clone = new Persons();
    clone.mItems = this.mItems.map(function(person) {
        return person.clone();
    });
    return clone;
  }
}

Person.prototype = {
  clone: function() {
    var clone = new Person(this.name);
    clone.score = this.score;
    return clone;
  }
}

这种方法的优势在于它将问题分开 - Person类不必知道如何克隆单个Person,它只需知道{{1}公开Person方法。如果clone添加了应在克隆中保留的新属性,则只需要更改Person

它通常是使用通用Person方法的反模式,例如:在这种情况下,来自jQuery或Underscore。他们最终会克隆您不想要的东西,或者遗漏您所做的事情(例如,clone可能最终会有Person或其他一些也需要克隆的对象。

答案 1 :(得分:0)

您可以使用[].mapObject.assign

Persons.prototype.clone = function() {
   var clone = new Persons();
   clone.mItems = this.mItems.map(function(person) {
     return Object.assign(new Person, person);
   });
   return clone;
};