简体   繁体   English

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

[英]How to deep copy (clone) an object with array members in Javascript?

Introduction 介绍

I have a Class Persons that contains an array of Person and functions : 我有一类Persons ,其中包含的阵列Person及功能:

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

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

The Class Person has members and functions : 班级Person具有成员和职能:

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

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

I want that the program does the following things : 我希望程序执行以下操作:

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

Question

I want to deep copy an instance of Persons to completely duplicate the Array of Person . 我想复制一个Persons实例以完全复制Person Array。 The Objects Person must be duplicated. 对象人必须重复。 The functions of the Objects must be kept. 对象的功能必须保留。

JQuery.extend() JQuery.extend()

JQuery.extend(true, {}, persons) clones the direct members of Persons but shallow copies the Person Objects. 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()) JSON.parse(json.stringify())

clonedPersons = JSON.parse(json.stringify(persons)) clones the Objects but remove the functions. clonedPersons = JSON.parse(json.stringify(persons))克隆对象,但删除函数。

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

Thank you for your answers. 谢谢您的回答。

If you're dealing with custom classes, you're going to want to implement custom clone methods. 如果要处理自定义类,则将要实现自定义clone方法。 Generally, in this context, I'd have 2 separate clone functions, one on the Person model and one on the Persons collection. 通常,在这种情况下,我将有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;
  }
}

The advantage to this approach is that it separates the concerns - the Person class doesn't have to know how to clone a single Person , it only has to know that Person exposes a clone method. 这种方法的优点是它可以将关注点分离开Person类不必知道如何克隆单个Person ,而只需知道Person公开了一个clone方法。 If Person adds a new property that should be persisted in the clone, only Person needs to change. 如果Person添加了应保留在克隆中的新属性,则仅需更改Person

It's generally an anti-pattern to use generic clone methods, eg from jQuery or Underscore, in this context. 在这种情况下,使用通用clone方法(例如来自jQuery或Underscore的方法)通常是一种反模式。 They'll end up cloning things you don't want, or missing things you do (eg a Person might eventually have an Address or some other object that will also need cloning). 他们最终会克隆您不想要的东西,或者丢失您要做的事情(例如,一个Person最终可能拥有一个Address或一些其他需要克隆的对象)。

You can use [].map and Object.assign : 您可以使用[].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;
};

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

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