I wish I had read this article when I started working with JavaScript.
It would have saved me a lot of bugs :)
Understanding how JavaScript handles references is a fundamental concept to understand not only because all the latest frontend frameworks/libraries (Angular, React, Next, Astro,...) and modern applications rely on local and global states that are objects and arrays, but also because they are indispensable techniques if you want to use some paradigms, libraries or patterns that require the use of immutable data (a topic that will be covered later in this book)
You should definitely read this chapter if you don't know what I mean when I talk about "Reference" vs "Value" or how to handle "shallow" and "deep" copies in JavaScript. At the end of the article you will also find an example built in React
JavaScript supports two main categories of data types: primitives and objects.
1. Primitives
Primitive data types include numbers, booleans, strings, symbols, as well as the special values null and undefined.
primitives
In TypeScript we can also explicitly specify the type, as shown below, but it is not necessary when you initialize the property thanks to the inference that we talk about in the dedicated chapter.
explicit types in primitives
2. Objects
The second category is objects. Particularly the plain object, arrays, functions, and more — are all objects.
objects
The typeof operator returns a string indicating the type of the operand's value. Source: MDN
Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
Assign a new value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
However, changing a property of an object referenced by a variable does change the underlying object.
Don't worry if it's still not clear. I try to explain these sentences in the next paragraphs
When using the strict comparison operator ===, two (primitive) variables having values are equal if they have the same value.
All of the below comparisons are equal:
But the comparison operator === works differently when comparing (object and array) references.
Two references are equal only if they reference exactly the same object (or array).
In JavaScript, you use variables to store values that can be primitive or references. When you make a copy of a value stored in a variable, you create a new variable with the same value.
For a primitive value, you just simply use a simple assignment:
However, if you use the assignment operator for a reference value, it will not copy the value.
Instead, both variables will reference the same object in the memory:
While this behavior does not generate errors, it is rarely this result is what we want to achieve.
As we saw in the previous example , the following snippet does not create a new cloned object but just a reference to the user:
So, how can we clone it? And how can we change the cloned properties without affect the source value?
We have several ways and now I will show you the most populars:
1. Object.assign
Object.assign is a method in JavaScript that allows you to copy the values of all enumerable properties from one or more source objects to a target object. It returns the target object.
Object.assign({}, user): creates a new empty object {} (and this is the real trick to create a new memory allocation) and copies all properties from user to this new object.
The new object cloned is a shallow copy of user.
Shallow vs. Deep Copy
Shallow Copy: Only copies properties at the first level. If an object property is an object itself, the reference to that nested object is copied, not the object itself.
Deep Copy: Copies all levels of an object. Each nested object is also copied, ensuring no references to the original object.
Here you can see an example of a shallow copy where you can see how the Object.assign works with nested object.
When we clone the user object and we update id and coords, the id value is copied, while the coords properties are not. They are still references.
In the previous example, user.lat has been changed to 1000 even if we updated cloned