CHAPTER 7Copying objects
Copying Values
In Javascript one can think that objects are separate from variables. A
variable groucho
doesn't directly "contain" the object, it just references it, so the object is stored somewhere else:
let groucho = { about: "I am a Marx", funny: true };
When we assign one variable to another, the object that is referenced is not copied, only the reference is (the pointer or memory address). So this initialization
let chicco = groucho;
produces this result
Copying objects by hand
To copy an object
by hand, we can write a loop (a for-in
) to copy all properties:
let copy = {};
for (const field in object) {
copy[field] = object[field];
}
This is called a shallow copy since the fields of object
are not copied, only their references are copied.
A special function Object.assign
makes this process easier. It receives an object as a first argument (this is the target) and assigns to it all fields of the second argument:
let copy = Object.assign({}, object);
Merging objects
If we want to merge two objects (take all fields of all of them), we can call Object.assign
with more than 2 arguments:
let model = { brand: "Tesla", model: "X" };
let config = { color: "red", battery: "90kWh" };
Object.assign({}, model, config);
// -> { brand: "Tesla", model: "X", color: "red", battery: "90kWh" }
Copying with spread
The same can be accomplished with the spread operator ...
, which inserts all fields of an object into a new one:
let chicco = { ...groucho };
To copy many objects, we can also use spread many times:
let car = { ...model, ...config };
If any field is explicitly initialized, it will overwrite any fields coming from the spread:
let car = { ...model, ...config, model: "Y" };
// -> { brand: "Tesla", model: "Y", color: "red", battery: "90kWh" }
Deep Copy
Whenever we need a deep copy, a function called structuredClone
will do it for us. This function clones the top object and any object inside it (the whole tree):
const obj = { a: 1, b: true, c: { d: null, f: "hi", e: [1, 2, 3] } };
const clone = structuredClone(obj);
console.log(obj === clone); // false (different objects)
console.log(clone);
// { a: 1, b: true, c: { d: null, f: 'hi', e: [ 1, 2, 3 ] } }