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:
- The deep-cloning is fine, as deeply nested objects still retain their properties - however, arrays need to be cloned too; replaced
obj.slice()
withobj.map(o => cloneObj(o))
. - This method is actually faster than
JSON.parse(JSON.stringify(obj))
- three tests on JSBench andJSON
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()"