I just came across this concept of
var copy = Object.assign({}, originalObject);
which creates a copy of original object into the \"
It creates a shallow copy, according to this paragraph from MDN:
For deep cloning, we need to use other alternatives because Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.
For the purposes of redux, Object.assign()
is sufficient because the state of a redux app only contains immutable values (JSON).
For small Data structures
I see that JSON.stringify()
and JSON.parse()
work nice.
// store as JSON
var copyOfWindowLocation = JSON.stringify(window.location)
console.log("JSON structure - copy:", copyOfWindowLocation)
// convert back to Javascript Object
copyOfWindowLocation = JSON.parse(copyOfWindowLocation)
console.log("Javascript structure - copy:", copyOfWindowLocation)
var copy = Object.assign({}, originalObject);
does a shallow copy which is changing the copy reflect changes in your original object also. So to perform deep copy I would recommend the lodash
cloneDeep
import cloneDeep from 'lodash/cloneDeep';
var copy = cloneDeep(originalObject);
Forget about deep copy, even shallow copy isn't safe, if the object you're copying has a property with enumerable
attribute set to false.
MDN :
The Object.assign() method only copies enumerable and own properties from a source object to a target object
take this example
var o = {};
Object.defineProperty(o,'x',{enumerable: false,value : 15});
var ob={};
Object.assign(ob,o);
console.log(o.x); // 15
console.log(ob.x); // undefined
As mentioned above, Object.assign()
will do a shallow clone, fail to copy the source object's custom methods, and fail to copy properties with enumerable: false
.
Preserving methods and non-enumerable properties takes more code, but not much more.
This will do a shallow clone of an array or object, copying the source's methods and all properties:
function shallowClone(src) {
let dest = (src instanceof Array) ? [] : {};
// duplicate prototypes of the source
Object.setPrototypeOf(dest, Object.getPrototypeOf(src));
Object.getOwnPropertyNames(src).forEach(name => {
const descriptor = Object.getOwnPropertyDescriptor(src, name);
Object.defineProperty(dest, name, descriptor);
});
return dest;
}
Example:
class Custom extends Object {
myCustom() {}
}
const source = new Custom();
source.foo = "this is foo";
Object.defineProperty(source, "nonEnum", {
value: "do not enumerate",
enumerable: false
});
Object.defineProperty(source, "nonWrite", {
value: "do not write",
writable: false
});
Object.defineProperty(source, "nonConfig", {
value: "do not config",
configurable: false
});
let clone = shallowClone(source);
console.log("source.nonEnum:",source.nonEnum);
// source.nonEnum: "do not enumerate"
console.log("clone.nonEnum:", clone.nonEnum);
// clone.nonEnum: – "do not enumerate"
console.log("typeof source.myCustom:", typeof source.myCustom);
// typeof source.myCustom: – "function"
console.log("typeof clone.myCustom:", typeof clone.myCustom);
// typeof clone.myCustom: – "function"
jsfiddle
By using Object.assign()
, you are actually doing Shallow Copy of your object. Whenever we do an operation like assigning one object to other, we actually perform a shallow copy, i.e. if OBJ1 is an object, modifying it through another object which is OBJ2 will reflect changes in OBJ1 too.