2025 Update
There's loads of options here (more than the ones I've listed).
Most of them are very readable; beyond that, each have their own pros and cons around performance, availability, and functionality.
I'll go through each that I list below:
- Spread Operator (
...)
Object.assign
- Structured Clone (
structuredClone
Spread Operator (...)
The spread syntax is probably the most general purpose syntax of all the options, this can be used on Functions, Arrays, and Objects:
// Functions
myFunction(a, ...iterableObj, b)
// Arrays
[1, ...iterableObj, '4', 'five', 6]
// Objects
{ ...obj, key: 'value' }
(Source: Docs)
This is quite an easy syntax to read but can be slower compared to other methods - this answer discusses that more.
Caniuse
Object.assign
Unlike spread, Object.assign is focussed on Objects ({}) only, but it carries a warning around deep-copying (where it recommends structuredClone).
You can also use it to copy multiple objects at once:
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
(Source: Docs)
Caniuse
Structured Clone (structuredClone)
I recently learnt about this method from this answer; structuredClone looks like a great method for making deep-copies of object.
Note that there a slightly different expectations when using the method for something like an ArrayBuffer, see Transferring an Object
We can use the buffer in the cloned object, but if we try to use the original buffer we will get an exception.
// Create an ArrayBuffer with a size in bytes
const buffer1 = new ArrayBuffer(16);
const object1 = {
buffer: buffer1,
};
// Clone the object containing the buffer, and transfer it
const object2 = structuredClone(object1, { transfer: [buffer1] });
// Create an array from the cloned buffer
const int32View2 = new Int32Array(object2.buffer);
int32View2[0] = 42;
console.log(int32View2[0]);
// Creating an array from the original buffer throws a TypeError
const int32View1 = new Int32Array(object1.buffer);
(Source: Docs)
Caniuse
Original Answer
If you want to clone an existing object, I'd recommend the "spread operator"
// interface user {
// name: string,
// jobTitle: string
// }
// const employee: user = {name: 'Liane', jobTitle: 'Web Dev'}
const employee = {name: 'Liane', jobTitle: 'Web Dev'}
const newEmployee1 = {
...employee,
name: 'James'
};
const newEmployee2 = {
...employee,
name: 'John'
};
console.log(employee)
console.log(newEmployee1)
console.log(newEmployee2)