Sobes.tech
Middle

What methods can be used to clone an object in JavaScript?

sobes.tech AI

Answer from AI

  • Spread operator ... (Shallow Copy).
  • Object.assign() (Shallow Copy).
  • JSON.parse(JSON.stringify(obj)) (Deep Copy, but with limitations).
  • Recursive function (Deep Copy).
  • Libraries (e.g., Lodash with method _.cloneDeep(), Deep Copy).

Comparison of Shallow vs. Deep Copy:

Copy Type Description Example
Shallow Copy Copies surface properties. Nested objects remain by reference. const newObj = { ...origObj }; / const newObj = Object.assign({}, origObj);
Deep Copy Copies all properties, including nested objects and arrays. const newObj = JSON.parse(JSON.stringify(origObj)); / Deep copy function / _.cloneDeep(origObj)

Limitations of JSON.parse(JSON.stringify(obj)):

  • Does not copy functions.
  • Does not copy undefined.
  • Does not copy Symbol.
  • Does not handle cyclic references.
  • Converts Date objects to strings.
  • Converts NaN, Infinity, and -Infinity to null.

Example of shallow copy with spread operator:

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York',
    zip: '10001'
  }
};

const shallowCopy = { ...originalObj };

shallowCopy.name = 'Bob'; // Only the copy changes
shallowCopy.address.city = 'Los Angeles'; // Both original and copy change (nested object by reference)

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // Los Angeles

Example of deep copy with JSON.parse(JSON.stringify()):

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York'
  },
  greet: function() {
    console.log('Hello');
  },
  undefinedProp: undefined
};

const deepCopy = JSON.parse(JSON.stringify(originalObj));

deepCopy.name = 'Bob';
deepCopy.address.city = 'Los Angeles';

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // New York
// console.log(deepCopy.greet); // undefined (function not copied)
// console.log(deepCopy.undefinedProp); // undefined (undefined not copied)

Example of recursive function for deep copying:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // Base case: primitives or null
  }

  // Handle Array
  if (obj instanceof Array) {
    const copy = [];
    for (let i = 0; i < obj.length; i++) {
      copy[i] = deepClone(obj[i]);
    }
    return copy;
  }

  // Handle Object
  if (obj instanceof Object) {
    const copy = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        copy[key] = deepClone(obj[key]);
      }
    }
    return copy;
  }

  // For other object types not needed in cloning scenario
  throw new Error("Unable to copy obj! Its type isn't supported.");
}

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York'
  },
  numbers: [1, 2, { three: 3 }]
};

const deepCopy = deepClone(originalObj);

deepCopy.name = 'Bob';
deepCopy.address.city = 'Los Angeles';
deepCopy.numbers[2].three = 4;

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // New York
// console.log(originalObj.numbers[2].three); // 3