This blog post is about reference and primitive data types and how they are stored in the computer’s memory with an example in React. The post is produced by Leo Kelmendi, one of Provide IT’s tech leads with over 7 years of experience in web and system development. You can read the original article here.
JavaScript and some other programming languages use two different types of RAM called Stack and Heap.
JavaScript’s Execution Cycle
As you can see in the image above, stack and heap two different memory sectors in RAM. These are used by JavaScript in different scenarios depending on the type of data being processed or requested from theevent loop.
Stack
Stacks are typically used for thread execution (). This means that when the next function in the program flow is called, a block at the top of the stack will be reserved for the function’s local variables and some other metadata. When the function returns, the block is freed and can be reused in the next function call.
Stack is basically an easily accessible data structure, which simply manages its objects as a heap. Only objects whose size is known from the beginning can be used in this heap, this applies to Number, Stringand Boolean.
Heap
Heap is a data structure for objects whose size and structure cannot be specified from the beginning. Since objects and arrays can be modified and changed during the program’s excavation, they must be placed in the heap. The heap can be thought of as a sorted heap compared to the stack.
For each heap item, the exact address is stored in a pointer that points to the item in the heap, since it is more difficult to allocate in the heap. The pointer, in turn, is stored in the stack.
What do Stack and Heap have to do with reference and primitive data types?
Primitive data types are stored on the stack because the size can be predetermined. While reference data types are stored on the heap because the size cannot be determined in advance. The memory pointers are stored on the stack to where the data is in the heap.
Primitive data types
Primitive data types are simplified when the size and structure of the data are known in advance. Examples of primitive data types in JavaScript are:
- Null
- Undefined
- Boolean
- Number
- String
Reference data types
Reference data types are data whose size and structure are dynamic and cannot be determined from the start, or are even unknown. In JavaScript, reference data types are, for example:
- Array
- Object
- Function
But why does this matter to developers?
The fact that only the memory pointers of reference data types are stored on the stack is of great importance. This often leads to unpredictable and strange behavior when using reference data types.
When can unpredictable behavior occur?
If we take an example with the React component below:
Here we see a shopping cart component that renders items and handles removal of items from the application state.However, if we look more closely at the deleteCartItemHandler This is because it can easily lead to unpredictable applications, which is considered a bad practice.
A better approach would be to copy the reference and then store the changes, or the so-called immutable way to handle reference types in JavaScript:
The only change that was made is when we retrieved information from items in the cart, we used JavaScript’s spread operator […object]. This is better because the spread operator actually copies all the values of the given reference directly from the heap, instead of just copying the pointer from the stack. This is considered a better way to change the data in the heap in an immutable way.
These are the JavaScript methods that can be used to copy reference values directly from the heap:
- […object] – spread operator
- [data].slice() — slice method
- Object.assign({}, obj) — copy of object
- JSON.parse(JSON.stringify(arr/ob)) — deep clone of object (objects must be serializable as JSON)
However, it is important to remember that some of these methods will create a copy of an object and not a deep clone.