Understanding JavaScript Objects, Memory Management, and Deep Copying: A Complete Guide

Dharmik B.Dharmik B.
4 min read

In JavaScript, objects are one of the most powerful data structures used to represent real-world entities. But behind the scenes, there's a whole world of memory management concepts like stack, heap, garbage collection, and memory leaks. This article breaks down everything you need to know—from the basics of objects to deep-copying techniques and memory internals in JS.

NOTE: This Article is Inspired by Hitesh Choudhary’s and Piyush Garg’s Web Cohort 1.0

What Are Data Structures?

Data structure refers to how you store your data in memory.

Examples:

  • Stack

  • Queue

  • Key-Value Pairs

Two Main Types of Data Structures:

  1. Primitive Data Structures

    • fundamental and immutable(Can’t change the value once created)

    • Example: string, number, boolean,

  2. Non-Primitive Data Structures

    • Custom implemented by the developer

    • Examples: Stack, Linked List, Graph

JavaScript Objects: The Real-World Representation

While arrays store data sequentially, objects store data in key-value pairs.

You use curly braces {} to define an object. Objects can also contain:

  • Arrays

  • Functions (called methods)

  • Nested objects

Example:

const person = {
    firstname: 'John',
    lastname: 'Wick',
    hobbies: ['reading', 'traveling'],
    ismarried: false,
    getfullname: function () {
        return "John Wick";
    },
    address: {
        house_no: 1,
        street: 3,
        countrycode: "US",
        state: "NY",
        pincode: 123456
    }
};

Use Case of Objects

Objects help group related data using keys. This concept is similar to SQL tables with key-value records.

Real World Analogy:

Let’s say we want to represent a remote in code:

const remote = {
    color: "black",
    brand: "Samsung",
    dimensions: {
        height: 10,
        width: 5,
        depth: 1
    },
    turnoff: function () {
        console.log("turning off the TV");
    },
    volumeup: function () {
        console.log("increasing the volume");
    }
}

How to Copy Objects in JavaScript (With Different Memory Locations)

Way 1: Using Spread Operator

let p1 = {
    fname: 'John',
    lname: 'Wick',
    address: {
        house_no: 1,
        street: 3,
        countrycode: "IN",
        state: "GJ",
        pincode: 360005
    }
};

let p2 = {
    ...p1
};

// ... = Spread operator
// spread operator generates shalllow copy of object
// (just copy the outer elements not nested objects e.g. address)

Problem:
This is a shallow copy. Nested objects are not duplicated; they still refer to the same memory.

Way 2: Deep Copy Using Serialization and Deserialization

let p1 = {
    fname: 'John',
    lname: 'Wick',
    address: {
        house_no: 1,
        street: 3,
        countrycode: "IN",
        state: "GJ",
        pincode: 360005
    }
};
// Serialization:
// conversion of object to string, then stored it in p1_string
const p1_string = JSON.stringify(p1);
// Deserialization:
// conversion of string to object, then stored it in p2
let p2 = JSON.parse(p1_string);

This method ensures that nested objects are copied too, giving p2 a completely different memory reference.

How Objects Are Stored in Memory

There are two types of memory in any programming language:

Stack Memory:

  • Stores primitive variables like strings, numbers, booleans.

  • Fixed size.

  • Fast read/write.

  • Automatically removed after execution.

const fname = "Spongebob";
const lname = "Squidward";

These will be stored in stack memory.

Heap Memory:

  • Stores non-primitive types like arrays, objects, graphs, trees.

  • Dynamically allocated.

  • Slower due to pointer lookups.

Example:

const p1 = {
    fname: "Piyush",
    lname: "Garg"
};

This object is stored in heap memory, but p1 (the reference/pointer) is stored in stack.

Let’s say heap memory address is 0x1, then:

  • p1 = 0x1 (in stack)

  • Object { fname, lname } = stored at 0x1 (in heap)

When we do:

let p2 = p1;

Now:

  • p2 = 0x1

  • Both p1 and p2 point to the same object.

Changes in p2 reflect in p1.

Garbage Collection in JavaScript

const p1 = {
    fname: "Piyush",
    lname: "Garg"
};

let p2 = p1;

If both p1 and p2 go out of scope (removed from stack), the object in heap (0x1) has no references.

JS Garbage Collector:

  • Automatically detects unreferenced heap data.

  • Frees memory.

In languages like C/C++:

You must manually:

  1. Free heap memory

  2. Remove pointers from stack

Memory Leak Explained

const p1 = { fname: "Piyush", lname: "Garg" };
let p2 = p1;

Now imagine, 2 developers works together on a project:

  • Dev1 uses p1

  • Dev2 uses p2

If Dev2 deletes p2 and the heap memory it points to (0x1), then p1 becomes a dangling pointer.

Now:

  • p1 points to memory with someone else’s data.

  • Any changes via p1 will corrupt that data.

This is called a Memory Leak

In languages without a Garbage Collector, developers must manually check if any pointer still exists before deleting memory.

In JavaScript, Garbage Collector handles it for you, ensuring safety.

Summary of Memory Behavior

Data TypeStored InNotes
Primitive typesStackFixed size
Non-primitiveHeapDynamic memory
PointersStackPoint to heap

Final Thoughts

Understanding how JavaScript handles objects and memory is crucial for writing efficient, bug-free code, especially as your apps scale. With these fundamentals, you're better equipped to handle performance, cloning issues, and even deep system-level questions in interviews or real-world projects.

0
Subscribe to my newsletter

Read articles from Dharmik B. directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dharmik B.
Dharmik B.