Hello everyone, learning JavaScript surely we must know Object. In some specific problems, sometimes we need to use ‘Clone Objects’ to perform different functions. This article will introduce you to ‘3 ways to clone objects in JavaScript’
Objects are a reference type
First time clone 1 obj I also use the assignment =
, log out the results are quite satisfactory
1 2 3 4 5 6 7 8 9 | <span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> one <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> two <span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> obj2 <span class="token operator">=</span> obj <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> obj <span class="token punctuation">,</span> <span class="token comment">// { one: 1, two: 2 };</span> obj2 <span class="token comment">// { one: 1, two: 2 };</span> <span class="token punctuation">)</span> |
However, when adding / modifying an item, see what happens
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> obj2 <span class="token punctuation">.</span> three <span class="token operator">=</span> <span class="token number">3</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> obj2 <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {one: 1, two: 2, three: 3}; <-- ✅</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> obj <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {one: 1, two: 2, three: 3}; <-- ?</span> |
Why was the original Object still affected? That’s because Object is a reference type, so when you use =
, it copies the pointer to the memory space it occupies, the reference types don’t hold values, they’re a pointer to the value. in memory. So we need to find another way to clone the object without affecting the ‘original’ object.
1. Use Spread
1 2 3 4 5 6 7 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> cloneFood <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> food <span class="token punctuation">}</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> cloneFood <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '?', bacon: '?' }</span> |
Using Spread will help us clone Obj. Note when using it you may need to compile with Babel
2. Use Object.assign
1 2 3 4 5 6 7 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> cloneFood <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> food <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> cloneFood <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '?', bacon: '?' }</span> |
In addition to the legendary IE, Object.assign
support is almost complete, Object.assign
is in the official release and we can use it to clone 1 Obj quickly. Read more about Object.assign ()
3. Use JSON
1 2 3 4 5 6 7 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> cloneFood <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">parse</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> food <span class="token punctuation">)</span> <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> cloneFood <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '?', bacon: '?' }</span> |
Shallow Clone vs Deep Clone
A slight comparison between “shallow” clone and “deep” clone. Let’s observe the following example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">const</span> nestedObject <span class="token operator">=</span> <span class="token punctuation">{</span> country <span class="token punctuation">:</span> <span class="token string">'??'</span> <span class="token punctuation">,</span> detail <span class="token punctuation">:</span> <span class="token punctuation">{</span> city <span class="token punctuation">:</span> <span class="token string">'vancouver'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> shallowClone <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> nestedObject <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token comment">// Changed our cloned object</span> shallowClone <span class="token punctuation">.</span> country <span class="token operator">=</span> <span class="token string">'??'</span> shallowClone <span class="token punctuation">.</span> detail <span class="token punctuation">.</span> city <span class="token operator">=</span> <span class="token string">'taipei'</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> shallowClone <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {country: '??', detail: {city: 'taipei'}} <-- ✅</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> nestedObject <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {country: '??', detail: {city: 'taipei'}} <-- ?</span> |
“Shallow” means that we only clone the first level, the deeper level will be interpreted as a reference. And when using method 3
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> deepClone <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">parse</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> nestedObject <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> deepClone <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {country: '??', detail: {city: 'taipei'}} <-- ✅</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> nestedObject <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// {country: '??', detail: {city: 'vancouver'}} <-- ✅</span> |
Object.assign vs Spread
Object.assign is a function that modifies and returns the target object . When using
1 2 | <span class="token keyword">const</span> cloneFood <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> food <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
{}
is interpreted as a modified object, the target object is not referenced by any variables at that time, but since Object.assign
returns the target object, we can store the assigned object. Results in the cloneFood
variable
1 2 3 4 5 6 7 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> food <span class="token punctuation">,</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'??'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> food <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '??', bacon: '?' }</span> |
Obviously the value of corn
in the food
object is wrong, so we can assign the correct value to corn
using Object.assign
. We really don’t use the return value of the function, but we are modifying the target object that we referenced with the food
object.
Spread
is a way of copying the properties of an object into a new object
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> food <span class="token punctuation">,</span> corn <span class="token punctuation">:</span> <span class="token string">'??'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token comment">// TypeError: invalid assignment to const `food'</span> |
...
cause an error, because we use Spread to create a new object and therefore are assigning a completely new object to the food
declared with const constants is wrong. The solution is to create a new variable to save the object
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">const</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> newFood <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> food <span class="token punctuation">,</span> corn <span class="token punctuation">:</span> <span class="token string">'??'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> newFood <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '??', bacon: '?' }</span> |
or we can use let
, var
to allow us to assign a completely new object
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">let</span> food <span class="token operator">=</span> <span class="token punctuation">{</span> corn <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">,</span> bacon <span class="token punctuation">:</span> <span class="token string">'?'</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> newFood <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> food <span class="token punctuation">,</span> corn <span class="token punctuation">:</span> <span class="token string">'??'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> newFood <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { corn: '??', bacon: '?' }</span> |
Conclude
Above I have introduced you to ‘3 ways to Clone Objects in JavaScript’, hoping to help you when working with Objects in JavaScript
If you find a good article, give me +1 upvote. If you like me, click the follow button for more cool stuff. Good luck !