Value and Reference
The fundamental difference between complex and primitive data types is how they are stored and copied. Primitives are strings
, numbers
, booleans
, null
and undefined
; when assigning, they are copied entirely, by value.
This is not the case with complex types. The variable to which an array or object is assigned does not store the value itself, but the address of its space in memory, i.e. a reference (pointer) to it, which occurs by reference.
Imagine a variable as a sheet of paper. Its value is a record on this sheet.
If you want to share this record with users, you can make physical copies and hand them to everyone, that is, make multiple independent copies (assignment by value).
Alternatively, place the sheet in a locked room and give users a key to this room, that is, they will have one shared copy (assignment by reference).
Now change the data on the sheet of paper, i.e. the value of your variable. Obviously, those with access to the room will always see the changes we make, since the original copy changes and they have access to it. It is also obvious that owners of paper copies will not notice the change when looking at their copies.
When assigning by value, a new storage cell is allocated to the variables, and data is copied into it. The example with multiple copies of a paper sheet is an illustrative example of this process (separate sheet for each copy).
When assigning by reference, instead of creating a new object, the variable is assigned a reference (pointer) to an existing object, i.e. to its space in memory. Thus, several variables can point to the same object, with a locked room (they have a key to access the original sheet), as it were.
All primitive types are assigned by value, that is, with a copy made.
let a = 5;
// Assignment by value, one more cell will be created in memory,
// with the value 5 copied
let b = a;
console.log(a); // 5
console.log(b); // 5
// Change the value of a
a = 10;
console.log(a); // 10
// The value of b has not changed since it is a separate copy
console.log(b); // 5
Complex types, i.e. objects, arrays, functions, are assigned by reference, that is, a variable simply receives a reference to an already existing object.
const a = ["Mango"];
// Since a is an array, a reference to an existing array in memory
// is written to b. Now a and b point to the same array.
const b = a;
console.log(a); // ["Mango"]
console.log(b); // ["Mango"]
// Change the array by adding another element, using the pointer from a
a.push("Poly");
console.log(a); // ["Mango", "Poly"]
// b has also changed because b, just like a,
// contains a reference to the same space in memory
console.log(b); // ["Mango", "Poly"]
// The result is repeated
b.push("Ajax");
console.log(a); // ["Mango", "Poly", "Ajax"]
console.log(b); // ["Mango", "Poly", "Ajax"]