← Back to list

I Unlearned JavaScript to Beat AI and const Was the First Liar

Unlearn & Relearn Series Part 2: If AI can write all the syntax, what are we left for? I went back to scratch to find out.

Faria Ejaz in JavaScript in Plain English · 2026-07-13 10:01 · 1 claps · 6.2 min read
#javascript #const #ai #immutability #web-development
Open on Medium ↗
Wiki topics: AI · AI · General LNG · Linguistics & Language 🌐 · Web Development

I Unlearned JavaScript to Beat AI and const Was the First Liar

AI generated image

AI generated image

Unlearn & Relearn Series Part 2: If AI can write all the syntax, what are we left for? I went back to scratch to find out.

We’re living in the golden age of code generation and it terrified me.

Copilot writes my components. ChatGPT drafts my utility functions. Claude refactors my classes in seconds. If you’re a software developer today, you can generate 500 lines of working React before you finish your morning coffee.

If AI can write all the syntax, generate all the boilerplate, and debug all the common errors… what am I actually left with? What am I actually worth?

Every job description screams for a “Problem Solver” but I’d quietly become the opposite. I was a Syntax Mechanic. Great at plugging things together, reading error messages, pasting the right Stack Overflow snippet. But the moment the AI hallucinated, the abstraction broke, or the bug didn’t have a Stack Overflow answer… I froze.

So I did something radical. I erased my mental whiteboard and went back to absolute scratch.

I unlearned the shortcuts. I unlearned the “just install this library” impulse. I unlearned blindly copy-pasting AI-generated code.

I forced myself to relearn JavaScript not the syntax, but the engine. Not how to write it, but why it executes the way it does.

Day 2 of that “Unlearn & Relearn” journey, I hit a wall I thought I’d already cleared years ago.

The Bug That Started It

I was writing a simple React state update. I used const for my object, because obviously const makes things immutable, right?

It didn’t. The UI froze. The state lied. The console showed the new value; the screen refused to update. I spent four hours questioning my sanity. I asked the AI for help. It told me to add a spread here and a spread there, but it couldn’t tell me why my perfectly valid const code was failing.

That’s when I realized: const had been gaslighting me for years.

If you’ve ever muttered “But I used const!" while staring at a frozen UI, stick with me. We're opening the hood of the JavaScript engine and looking at the Stack and the Heap where variables live, and where objects actually sit.

We learn const on day one of JavaScript:

const PI = 3.14;
PI = 3.15; // ❌ TypeError: Assignment to constant variable.

It throws an error. I internalized this as: “const means it cannot change. Period."

Then I moved to objects:

const car = { brand: 'Toyota' };
car.brand = 'Honda'; // No error!
console.log(car.brand); // 'Honda'

The engine let it slide. No error.

My assumption was: “const works for simple values but somehow breaks for objects." Wrong. It works exactly the same in both cases. My mental model was wrong about what const actually protects, not the language.

Where This Actually Bites: React State

Here’s where the pain starts especially - in React.

import { useState } from 'react';

function App() {
  const [user, setUser] = useState({ name: 'Ali', age: 30 });
  const handleClick = () => {
    user.age = 31;     // ❌ Mutating the object directly
    setUser(user);     // Passing the SAME reference
  };
  return <div>{user.age}</div>;
}

I click the button. Nothing happens. The component doesn’t re-render.

Why? React uses referential equality (===) to decide if state changed. When I pass user back into setUser, React checks: is this the same reference in memory as the previous state?

It is. So React shrugs: “Nothing changed. Skipping render.”

The AI told me to use const. It never told me that const only protects the variable binding, not the data sitting inside it.

What’s Actually Happening in Memory

To become a problem solver, I had to understand how JavaScript actually stores data in memory. It splits into two areas:

  • Stack (the call stack): holds primitive values and references. Fixed size, fast to access.
  • Heap (the memory heap): holds objects, arrays, and functions. Dynamic size, slower to allocate.

When I write const user = { name: 'Ali' }:

  1. JavaScript creates { name: 'Ali' } in the Heap. It gets a memory address say, 0x1234.
  2. JavaScript stores that address, 0x1234, in the Stack under the name user.
  3. const locks the Stack slot.
  4. user = { name: 'Bob' } tries to point the Stack slot at a new address, 0x5678. ❌ Blocked, this is what const actually prevents.
  5. user.name = 'Bob' reaches into the Heap at 0x1234 and edits the object directly. ✅ Fully allowed - the Stack still holds 0x1234, untouched.

Visualized:

Stack (Fixed)              Heap (Dynamic)
+-------------+            +---------------------------+
| user: 0x1234| ---------->| { name: 'Ali', age: 30 } |
+-------------+            +---------------------------+
      ^                            |
      |                            |
  const locks THIS           But the object inside
   (the address)             is FREE to mutate!

So const says: "You cannot reassign this variable to a new address." It never says: "You cannot modify the house at that address."

Four Places This Illusion Breaks in Modern JS

Trap 1: React State (the useState betrayal). Already covered above. The fix: create a new reference.

// ❌ Mutates the old object
user.age = 31;
setUser(user);

// ✅ Creates a NEW object in the Heap
setUser({ ...user, age: 31 });

Trap 2: Redux reducers (the silent mutation). Redux also relies on strict referential equality.

// ❌ BAD: mutates the existing state array
const reducer = (state = [], action) => {
  state.push(action.payload); // same array reference!
  return state; // Redux thinks nothing changed
};

// ✅ GOOD: creates a new array reference
const reducer = (state = [], action) => {
  return [...state, action.payload]; // new Heap address
};

Trap 3: Object.freeze() (the shallow betrayal).

const config = Object.freeze({ api: 'v1', nested: { key: 'value' } });
config.api = 'v2';              // ❌ fails silently or throws in strict mode
config.nested.key = 'newValue'; // ✅ SUCCEEDS — freeze is SHALLOW

The fix: use a library like Immer, or recursively freeze every nested property yourself.

Trap 4: TypeScript’s readonly (the compile-time illusion).

interface User { readonly name: string; }
const user: Readonly<User> = { name: 'Ali' };
user.name = 'Bob'; // ❌ TypeScript compile error only

TypeScript disappears at runtime. Compiled to plain JS, that protection is gone, mutate it in production and the browser won’t care what your types said.

Why JavaScript Designed It This Way

Why doesn’t JavaScript make const deeply immutable by default? Performance. Imagine recursively freezing a massive nested object, a Redux store with 10,000 entries, every single time it's declared. The app would grind to a halt.

JavaScript gives you the cheap primitive (lock the pointer) and trusts you to handle the complexity yourself, with spread operators or dedicated libraries.

The mindset I relearned the hard way:

  • Use const to protect against accidental reassignment.
  • Use the spread operator or structuredClone() to create a new reference whenever the underlying data needs to change.
  • Never mutate an object that’s shared across more than one part of the app.

Breaking It on Purpose

I broke it on purpose in the console to feel the pain firsthand:

// Misuse 1: The "constant" array
const arr = [1, 2, 3];
arr.push(4);     // ✅ works — array is mutated
console.log(arr); // [1, 2, 3, 4]
arr = [5, 6];    // ❌ TypeError — reassignment blocked

// Misuse 2: The function parameter trap
function impureUpdate(obj) {
  obj.newProp = 'I mutated the input!';
}
const state = { a: 1 };
impureUpdate(state);
console.log(state); // { a: 1, newProp: 'I mutated the input!' } - caller didn't expect this

// Misuse 3: structuredClone - shallow vs. deep
const original = { deep: { nested: true } };
const copy = structuredClone(original); // native deep clone
copy.deep.nested = false;
console.log(original.deep.nested); // true - safe

The Actual Point

In the AI era, it’s easy to tell an AI “make this object immutable using const," trust the output, and ship broken state management without ever knowing why.

I nearly was that person. I was coasting on AI-generated syntax, quietly terrified of the day it wouldn’t work and I wouldn’t know why.

That’s why I went back to zero. I unlearned the illusion that const is a magic shield. I relearned the Stack vs. Heap, the ancient, unchanging memory model that's sat underneath every JS engine for decades.

A problem solver doesn’t just know the syntax. They look at the memory model. They know const locks the pointer, but the data is fair game.

When my component won’t re-render, I don’t guess anymore. I check the reference: did I pass the exact same object back into state? If so, I spread it, clone it, or reach for Immer.

AI writes the syntax. I protect the integrity of the data. That, right there, is what every “Problem Solver” job description is actually hunting for.

TL;DR — Save This

  • **const prevents:** reassigning the variable (=)
  • **const does not prevent:** mutating object properties (obj.key = x) or array methods (.push())
  • Why React won’t re-render: setState received the same object reference — React thinks nothing changed
  • The fix: create a new reference — { ...obj }, [...arr], or structuredClone(obj)
  • “True” immutability: Object.freeze() (shallow) or a library like Immer

What’s Next

Next week, I’m continuing the “**Unlearn & Relearn*” series. AI keeps telling me to "use setTimeout" to fix rendering issues, but never explains why* the thread locks up in the first place. Unlearning that one too.

If this resonated, give it 50 claps 👏, drop a comment about your own “unlearn and relearn” moment, and follow for the next deep dive.


메타데이터
post_id
d75831208e00
slug
i-unlearned-javascript-to-beat-ai-and-const-was-the-first-liar-d75831208e00
url
https://medium.com/@fariaejaz/i-unlearned-javascript-to-beat-ai-and-const-was-the-first-liar-d75831208e00
canonical_url
https://medium.com/@fariaejaz/i-unlearned-javascript-to-beat-ai-and-const-was-the-first-liar-d75831208e00
author_url
https://medium.com/@fariaejaz
status
ok
fetched_at
2026-07-14 20:05:20