This is good for shallow cloning. The object spread is a standard part of ECMAScript 2018.
For deep cloning you'll need a different solution.
const clone = {...original}
to shallow clone
const newobj = {...original, prop: newOne}
to immutably add another prop to the original and store as a new object.
EDIT: When this answer was posted, {...obj}
syntax was not available in most browsers. Nowadays, you should be fine using it (unless you need to support IE 11).
Use Object.assign.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
However, this won't make a deep clone. There is no native way of deep cloning as of yet.
EDIT: As @Mike 'Pomax' Kamermans mentioned in the comments, you can deep clone simple objects (ie. no prototypes, functions or circular references) using JSON.parse(JSON.stringify(input))
If the methods you used isn't working well with objects involving data types like Date, try this
Import _
import * as _ from 'lodash';
Deep clone object
myObjCopy = _.cloneDeep(myObj);
if you don't want to use json.parse(json.stringify(object)) you could create recursively key-value copies:
function copy(item){
let result = null;
if(!item) return result;
if(Array.isArray(item)){
result = [];
item.forEach(element=>{
result.push(copy(element));
});
}
else if(item instanceof Object && !(item instanceof Function)){
result = {};
for(let key in item){
if(key){
result[key] = copy(item[key]);
}
}
}
return result || item;
}
But the best way is to create a class that can return a clone of it self
class MyClass{
data = null;
constructor(values){ this.data = values }
toString(){ console.log("MyClass: "+this.data.toString(;) }
remove(id){ this.data = data.filter(d=>d.id!==id) }
clone(){ return new MyClass(this.data) }
}
You can do it like this as well,
let copiedData = JSON.parse(JSON.stringify(data));
Following on from the answer by @marcel I found some functions were still missing on the cloned object. e.g.
function MyObject() {
var methodAValue = null,
methodBValue = null
Object.defineProperty(this, "methodA", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
},
enumerable: true
});
Object.defineProperty(this, "methodB", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
}
});
}
where on MyObject I could clone methodA but methodB was excluded. This occurred because it is missing
enumerable: true
which meant it did not show up in
for(let key in item)
Instead I switched over to
Object.getOwnPropertyNames(item).forEach((key) => {
....
});
which will include non-enumerable keys.
I also found that the prototype (proto) was not cloned. For that I ended up using
if (obj.__proto__) {
copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
PS: Frustrating that I could not find a built in function to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With