-1

I would like to make a deep copy (break references) without turning date objects into strings, how would I do that?

let a = [{
  date: new Date()
}, {
  name: 'John'
}];

// let b = a.slice(); // This copies the object reference, which is wrong (we want a COPY of the obejcts)
// let b = [...a]; // This copies the object reference, which is wrong (we want a COPY of the obejcts)
// let b = JSON.parse(JSON.stringify(a)); // This makes the date a string, which is wrong (we want date objects, not strings)

let b = a.slice();
a[1].name = 'PETER';

console.log(a);
// [ { date: 2020-06-08T09:10:32.530Z }, { name: 'PETER' } ]
console.log(b);
// [ { date: 2020-06-08T09:10:32.530Z }, { name: 'PETER' } ]

Here is a good answer on Javascript Deep Copying: Copy array by value

Frank
  • 2,109
  • 7
  • 25
  • 48
  • Would you mind posting a more elaborate answer please? :) I don't see how map would help here? – Frank Jun 08 '20 at 09:25
  • As far as I know the best way to make deep clone of array of objects is with help of either `Object assign` or `spread operator`. You can read it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax – gorak Jun 08 '20 at 09:30
  • If you want to "deep copy" an object then you must test each value to see if it's a primitive or not and if it's an object, apply different strategies to different kinds of object. Copying a date is simply `new Date(+date)`, copying a DOM element is somewhat trickier but not impossible. – RobG Jun 08 '20 at 12:07
  • Probably a duplicate of [*How do I correctly clone a JavaScript object?*](https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object) – RobG Jun 08 '20 at 20:14

3 Answers3

0

Here is a utility to deep copy the objects. Hope this helps

const deepCopy = (objectToBeCloned) => {
  let resultObj, value, key

  if (typeof objectToBeCloned !== "object" || objectToBeCloned === null) {
    return objectToBeCloned
  }

  if(typeof objectToBeCloned === "object") {
    if(objectToBeCloned.constructor.name !== "Object") {
      resultObj = new objectToBeCloned.constructor(objectToBeCloned)
    } else {
      resultObj = Array.isArray(objectToBeCloned) ? [] : {}
    }
  }

  for (key in objectToBeCloned) {
    value = objectToBeCloned[key]

    // Recursively copy for nested objects & arrays
    resultObj[key] = deepCopy(value)
  }

  return resultObj
}

let a = [{
  date: new Date(),
  x: {y:{z:1}},
  test: [1,2,3,4],
  testArrObj: [{x:1, y:2}]
}, {
  name: 'John'
}];

let b = deepCopy(a)
a[1].name = "PETER";
console.log(b);
console.log(a);


console.log(a === b)
console.log(b === b)
Nithish
  • 5,393
  • 2
  • 9
  • 24
0

Basic deep clone with date + timezone support written in Typescript (remove the types if not required).

export function clone<T>(x: T) {

    // JSON to string 
    var to = (k: string, v: any) => {

        // Serialise date with timezone 
        if (v && v instanceof Date) {
            return v.toUTCString()
        }

        return v
    }

    // String to JSON
    var from = (k: string, v: any) => {

        // Restore date
        if (v && typeof v == "string" && v.indexOf("Z") > -1 && moment(v).isValid()) {
            return new Date(v)
        }

        return v
    }

    return JSON.parse(JSON.stringify(x, to), from) as T
}

let a = [{
  date: new Date(),
  x: {y:{z:1}},
  test: [1,2,3,4],
  testArrObj: [{x:1, y:2}]
}, {
  name: 'John'
}];

let b = clone(a)
a[1].name = "PETER";
console.log(b);
console.log(a);


console.log(a === b)
console.log(b === b)

Note: An improvement would be to remove the moment dependency.

Learner
  • 2,459
  • 4
  • 23
  • 39
-1

This will deep copy the object, let me know if this resolves your issue:

let a = [{ date: new Date() }, { name: 'John'}];
let b = a.map(k=>({...k}));

a[1]="PETER";
console.log(a);
console.log(b);
gorak
  • 5,233
  • 1
  • 7
  • 19
  • That does not "break the reference", it copies the reference so `a[0].date === b[0].date`. – RobG Jun 08 '20 at 12:16
  • It does not copy nested objects if any. Nested objects will still have the same reference. – Nithish Jun 08 '20 at 12:23
  • @NithishGandesiri Yes, I know, this is the data that OP has shared and I have provided my answer on the basis of that. – gorak Jun 08 '20 at 12:28
  • Sorry @gorak, I just told because in the question it's being mentioned that deep copy is the requirement. – Nithish Jun 08 '20 at 14:57
  • 1
    @gorak Yes this is perfect. To the other comments here, I might have phrased the question wrong? But regardless this seems to solve my problem. – Frank Jun 10 '20 at 06:55