How JavaScript Stores Primitive Values in Memory

Primitive values in JavaScript are stored directly in the variable's memory slot on the stack. Learn how this works, why primitives are immutable, and what happens during assignment.

6 min read

JavaScript primitive memory storage works by keeping the value directly inside the variable itself. When you declare a variable and assign a primitive value to it, the engine stores that value directly in a memory region commonly called the stack. The variable's memory slot contains the actual data, not a pointer to somewhere else.

This direct storage model explains why primitives behave the way they do during assignment, comparison, and mutation.

Primitive values stored directly on the stack
Stack and heap are an engine detail, not a language rule

The ECMAScript spec never mandates a stack or a heap. "Stack for primitives, heap for objects" is the mental model most engines like V8 follow in practice, and it is the right way to reason about the behavior in this article. Just do not treat it as a guarantee documented in the spec itself.

Each variable owns its value completely. There is no sharing, no indirection, and no hidden connection between variables.

When you assign a primitive to another variable, JavaScript copies the value into a new memory slot. The two slots are independent.

The Stack: Direct Value Storage

The stack is a region of memory that follows a last-in, first-out structure. It is fast to allocate and deallocate because it only tracks the top of the stack. JavaScript uses the stack for primitive values and for storing references to objects.

When you declare a variable inside a function, its value goes onto the stack. When the function returns, that stack space is automatically reclaimed. This is why local variables inside functions are destroyed when the function finishes.

javascriptjavascript
function demo() {
  let message = "hello";  // "hello" goes on the stack
  let score = 10;         // 10 goes on the stack
  // both are destroyed when demo returns
}
demo();

The variables message and score each get their own slot on the stack with their own copy of the value. Nothing is shared between them. This direct, independent storage is the foundation of how primitives work.

What Immutable Really Means

Primitive values are immutable, which means you cannot change the value itself. Any method that appears to modify a primitive actually creates and returns a brand new value. The original is untouched.

javascriptjavascript
let greeting = "hello";
let upper = greeting.toUpperCase();
 
console.log(greeting); // "hello" (unchanged)
console.log(upper);    // "HELLO" (new string)

The toUpperCase method did not modify the original string "hello". It could not, because primitives are immutable. Instead, it created a brand new string "HELLO" and returned it.

The variable greeting still holds the original "hello".

This is different from objects, where methods can modify the object in place. Understanding immutability helps you predict what your code does. If a variable holds a primitive, its value never changes unless you explicitly reassign the variable itself.

javascriptjavascript
let points = 10;
points = points + 5; // not mutating the number 10; creating a new number 15
console.log(points); // 15

The plus operator did not change the number 10. It computed a new number 15 and assigned that to points, replacing the old value.

Assignment Creates Independent Copies

When you assign a primitive variable to another variable, JavaScript copies the value into a new memory slot. After the assignment, the two variables are completely independent.

javascriptjavascript
let original = 50;
let duplicate = original;
 
duplicate = 100;
console.log(original);  // 50
console.log(duplicate); // 100

The variable duplicate received a copy of the number 50. Reassigning duplicate to 100 only affected its own memory slot. The original variable was never touched.

This behavior is consistent across all primitive types: strings, numbers, booleans, null, undefined, symbols, and bigints.

This is fundamentally different from objects. If original held an object instead of a number, duplicate would receive a reference to the same object, and mutating duplicate would also affect original. For a complete comparison of these two behaviors, see the primitive vs reference types guide.

Why Primitives Are Compared by Value

Because each primitive variable holds its own copy of the value, comparing two primitives compares the actual data. Two primitives are equal if they contain the same value, regardless of where that value came from.

javascriptjavascript
let a = "test";
let b = "test";
let c = "other";
 
console.log(a === b); // true (same value)
console.log(a === c); // false (different value)
 
let x = 3.14;
let y = 3.14;
console.log(x === y); // true (same value)

The comparison operator checks the actual values stored in each variable's memory slot. It does not care whether the values came from the same source or were computed differently. If the bits are the same, the comparison returns true.

The Practical Impact

Understanding stack storage and immutability matters for two practical reasons. First, it means you never need to worry about accidentally sharing primitive data between parts of your code. Every assignment is a safe, independent copy.

Second, it means methods that seem to transform a primitive always return a new value. If you forget to capture the return value, your code silently does nothing:

javascriptjavascript
let name = "alex";
name.toUpperCase();       // returns "ALEX" but you ignored it
console.log(name);        // "alex" (unchanged)
 
name = name.toUpperCase(); // capture the returned value
console.log(name);         // "ALEX"

This is a common beginner mistake. The method toUpperCase returns a new string, but if you do not assign it to a variable, the result is lost. The original string remains unchanged because primitives are immutable.

For a complete list of all primitive types and their characteristics, see the JavaScript data types guide. To understand how memory works for the other category of values, read the primitive vs reference types guide.

Rune AI

Rune AI

Key Insights

  • Primitives are stored directly on the stack, not on the heap.
  • Each variable holds its own copy of the primitive value.
  • Primitives are immutable: methods return new values instead of modifying.
  • Assignment creates an independent copy, never a shared reference.
  • Objects, by contrast, are stored on the heap with pointer references.
RunePowered by Rune AI

Frequently Asked Questions

Where are primitive values stored in JavaScript?

Primitive values are stored directly on the stack. The variable's memory slot contains the actual value itself, not a pointer to it. This is why primitives are copied by value during assignment.

What does immutable mean for primitives?

Immutable means the value itself cannot be changed. Methods like toUpperCase on a string do not modify the original string. They return a brand new string with the transformation applied.

Are bigint and symbol also stored on the stack?

Yes. All 7 primitive types in JavaScript, including bigint and symbol, are stored directly in the variable's memory slot. Only objects are stored on the heap with a reference pointer on the stack.

Conclusion

Primitive values are stored directly on the stack inside the variable's memory slot. They are immutable, meaning any method that appears to change a primitive actually returns a new value. Assignment always creates an independent copy. This stack-based, copy-by-value behavior is what makes primitives predictable and safe.