Skip to content Skip to sidebar Skip to footer

Deep-Cloning An Object Using Object.fromEntries()

Sometime ago, I read about the proposal of the new method Object.fromEntries() that is supported on newer versions of some browsers (reference). While reading about it, I had in mi

Solution 1:

You are missing one thing:

else if (Array.isArray(obj))
  return obj.slice();

This will return a shallow copy of the array. If the array contains objects, those underlying objects will not be cloned:

const obj = [
  ['foo']
];

const cloneObj = (obj) =>
{
    if (typeof obj !== "object")
       return obj;
    else if (Array.isArray(obj))
       return obj.slice();

    return Object.fromEntries(Object.entries(obj).map(
        ([k,v]) => ([k, cloneObj(v)])
    ));
}

// Clone the original object.
let newObj = cloneObj(obj);

// Make changes on the original object.
obj[0][0] = 'bar';

// Display both objects on the console.
console.log("Original object: ", obj);
console.log("Cloned object: ", newObj);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

To fix it, return obj.map(cloneObj); instead:

const obj = [
  ['foo']
];

const cloneObj = (obj) =>
{
    if (typeof obj !== "object")
       return obj;
    else if (Array.isArray(obj))
       return obj.map(cloneObj);

    return Object.fromEntries(Object.entries(obj).map(
        ([k,v]) => ([k, cloneObj(v)])
    ));
}

// Clone the original object.
let newObj = cloneObj(obj);

// Make changes on the original object.
obj[0][0] = 'bar';

// Display both objects on the console.
console.log("Original object: ", obj);
console.log("Cloned object: ", newObj);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Solution 2:

  1. The deep-cloning is fine, as deeply nested objects still retain their properties - however, arrays need to be cloned too; replaced obj.slice() with obj.map(o => cloneObj(o)).
  2. This method is actually faster than JSON.parse(JSON.stringify(obj)) - three tests on JSBench and JSON was slower by more than 10% every single time.

Solution 3:

As already mentioned, your arrays are not deep-cloned - use obj.map(cloneObj) instead of obj.slice().

But another oversight is typeof obj !== "object", which doesn't work for null. Better use Object(obj) !== obj.


Post a Comment for "Deep-Cloning An Object Using Object.fromEntries()"