Code of the Day
BeginnerLanguage basics

Values and binding

const, let, and the values they point at — the foundation everything else in JS sits on.

JavaScript / TSBeginner9 min read
By the end of this lesson you will be able to:
  • Choose between const and let (and avoid var)
  • Distinguish primitives from objects, and value-copy from reference-copy
  • Explain why const does not mean "the value can't change"

JavaScript binds names to values much like Python does, but with its own rules and a couple of famous traps. Getting binding right early prevents a whole class of confusing bugs — especially the "why did changing this also change that?" variety.

const and let (not var)

Declare with const by default; use let only when you genuinely need to reassign the name. Avoid var — its scoping rules are a legacy footgun that modern JavaScript replaced for good reasons (one consequence is , where var declarations are silently moved to the top of their function scope).

const name = "Ada";   // cannot be reassigned
let count = 0;        // can be reassigned
count = count + 1;

Reaching for const first is a small habit with a big payoff: a name that can't be reassigned is one less thing to track when reading code.

const binds the name, not the value

This is the subtlety that trips everyone up. const freezes the binding — the arrow from name to value — not the value itself:

const user = { name: "Ada" };
user.name = "Grace";   // ✓ allowed — we mutated the object, not the binding
user = {};             // ✗ TypeError — repointing the const binding

So const protects the arrow, not the thing it points at. To make the object itself unchangeable you'd need something more (like Object.freeze).

Primitives vs objects

Values come in two camps, and they're copied differently:

  • number, string, boolean, null, undefined, symbol, bigint. Copied by value: you get an independent copy.
  • Objects — including arrays and functions. Copied by reference: you copy the arrow, not the thing it points to.
let a = 1;
let b = a;     // b is its own copy
b = 2;         // a is still 1

const xs = [1, 2];
const ys = xs; // ys points at the SAME array
ys.push(3);    // xs is now [1, 2, 3] too — one array, two names

See it for real — this runs in your browser:

JavaScript — editable, runs in your browser

Making a real copy

When you do want an independent copy of an array, you have to build a brand-new one. The usual tool is the spread syntax, written as three dots ...:

const xs = [1, 2, 3];
const ys = [...xs];   // a new array containing the same items
ys.push(4);
// xs is still [1, 2, 3]; ys is [1, 2, 3, 4] — they're separate objects

Read [...xs] as: "make a new array [ ], and spread the items of xs into it, one by one." Two things are happening:

  • The square brackets [ ] create a fresh array — a new object, so a new arrow (the whole point of the previous section).
  • ...xs expands xs into its individual elements (1, 2, 3), which become the contents of that new array — as if you'd typed [1, 2, 3] by hand.

Because ys now points at a different array, pushing to ys can't reach back and change xs. You copied the value, not just the arrow.

Objects use the same idea with curly braces:

const user = { name: "Ada" };
const copy = { ...user };   // a new object with the same fields

See the difference for yourself — change [...xs] to just xs and watch the original get clobbered too:

JavaScript — editable, runs in your browser

Spread makes a shallow copy — it duplicates the top level only. If an array holds other arrays or objects, those inner ones are still shared between the copies. That's fine for most beginner cases; we'll revisit deep copies later.

Equality follows the same rule

Because objects are references, two different objects with identical contents are not equal — === compares identity, not contents:

{} === {}            // false — two different objects
const o = {}; o === o // true  — same object
1 === 1              // true  — primitives compare by value

"Two names, one object" is behind a huge share of beginner bugs. Whenever you copy an object or array, ask: did I copy the value, or just another arrow to the same thing? If you need a real copy, copy it explicitly (e.g. [...xs]).

Where to go next

With binding solid, the next big idea in JavaScript is how it handles work that takes time — async and the event loop, in the intermediate track.

Add to an array without mutating itJavaScript

Write withItem(arr, item) so it returns a NEW array with item added to the end, leaving the original array untouched. This is the reference-vs-value idea from the lesson in practice.

withItem([1, 2], 3)[1, 2, 3]
Finished reading? Mark it complete to track your progress.

On this page