Skip to content

Instantly share code, notes, and snippets.

@yehezkieldio
Created July 20, 2025 07:21
Show Gist options
  • Save yehezkieldio/f0b46e04a196dbb9b34b683b47dcc55d to your computer and use it in GitHub Desktop.
Save yehezkieldio/f0b46e04a196dbb9b34b683b47dcc55d to your computer and use it in GitHub Desktop.

Revisions

  1. yehezkieldio created this gist Jul 20, 2025.
    81 changes: 81 additions & 0 deletions MEMORY_MODEL.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    **Key Takeaway: JS/TS is ALWAYS Pass-by-Value.** The "value" being passed is either a primitive directly, or a reference (a pointer) to an object.

    ---

    ### 1. Primitives (Stack-like Behavior, Value Copied)

    * **Types:** `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, `undefined`
    * **What's Passed:** An exact **copy of the value** itself.
    * **Behavior:**
    * When you pass a primitive to a function, the function gets its own, independent copy.
    * **Re-assigning** the parameter inside the function **does not affect** the original variable outside.
    * **Rust Analogy:** Very similar to passing a `Copy` type (e.g., `u32`, `bool`) by value in Rust.

    **Example:**

    ```typescript
    function modifyPrimitive(x: number) {
    x = 42; // This 'x' is a local copy.
    console.log(`Inside: x = ${x}`); // 42
    }

    let num = 10;
    console.log(`Before: num = ${num}`); // 10
    modifyPrimitive(num);
    console.log(`After: num = ${num}`); // 10 (Original 'num' is unchanged)
    ```

    ---

    ### 2. Objects (Heap Behavior, Reference Copied)

    * **Types:** `object`, `array`, `function`, `Date`, `Map`, `Set`, `class` instances, `RegExp`, `Promise`, `Error`, etc.
    * **What's Passed:** A **copy of the reference** (a pointer/memory address) to the object on the heap.
    * **Behavior:**
    * Both the original variable and the function's parameter now point to the **same object** in memory.
    * **Mutating properties** of the object *through* the function parameter **IS visible** to the original variable. (Think `&mut T` in Rust, where you can modify the data through the reference).
    * **Re-assigning** the parameter variable itself to a *new* object **is NOT visible** to the original variable. This just makes the local parameter point to a different object, leaving the original variable untouched. (Think `let mut x = ...; x = new_value;` for a local variable, it doesn't affect an outside binding).
    * **Rust Analogy:**
    * Passing an object reference is like passing `&T` (for reading) or `&mut T` (for modifying properties) in Rust. You're working with the same underlying data.
    * There's no explicit ownership transfer like in Rust; multiple references can point to the same object simultaneously. Memory management (garbage collection) handles deallocation when no references remain.

    **Examples:**

    ```typescript
    // --- Case A: Mutating the object's properties (Visible outside) ---
    function modifyArrayInPlace(arr: number[]) {
    arr.push(99); // Mutates the *original* array pointed to by 'arr'
    arr[0] = 100; // Also visible outside
    console.log(`Inside (mutation): arr =`, arr); // [100, 2, 99]
    }

    const myArray = [1, 2];
    console.log(`Before (mutation): myArray =`, myArray); // [1, 2]
    modifyArrayInPlace(myArray);
    console.log(`After (mutation): myArray =`, myArray); // [100, 2, 99] (Changed!)

    // --- Case B: Re-assigning the parameter itself (NOT visible outside) ---
    function reassignParameter(obj: { key: string }) {
    obj = { key: "new object" }; // 'obj' now points to a *new*, different object.
    console.log(`Inside (re-assignment): obj =`, obj); // { key: 'new object' }
    }

    let myObject = { key: "original object" };
    console.log(`Before (re-assignment): myObject =`, myObject); // { key: 'original object' }
    reassignParameter(myObject);
    console.log(`After (re-assignment): myObject =`, myObject); // { key: 'original object' } (Unchanged!)
    ```

    ---

    ### Cloning in JS/TS

    * **No Implicit Deep Cloning:** Unlike Rust's `Clone` trait which can be implemented for deep copies, JS/TS functions generally create **shallow copies** by default.
    * **Shallow Copy:** Copies the top-level structure, but nested objects are still references to the original nested objects.
    * `[...originalArray]`
    * `{ ...originalObject }`
    * `Object.assign({}, originalObject)`
    * **Deep Copy:**
    * `structuredClone(obj)`: The modern, preferred built-in way (available in most modern environments). Handles many complex types but not functions or DOM nodes.
    * `JSON.parse(JSON.stringify(obj))`: A hacky method, with significant limitations (loses functions, `undefined`, turns `Date` objects into strings, etc.).
    * Third-party libraries (e.g., Lodash's `_.cloneDeep`): Offer more robust deep cloning solutions.