Constants
const locks the binding, not the value - objects and arrays declared with const are still mutable.
const locks a variable's binding - you cannot reassign the name. It does not make the value immutable.
Attempting to reassign a const binding throws a TypeError at runtime and is caught at parse time by TypeScript and most linters.
const x = 1;
x = 2; // TypeError: Assignment to constant variable.An object bound by const is still mutable. Its properties can be changed freely because the binding (the pointer) is fixed, not the data it points to.
const config = { retries: 3 };
config.retries = 5; // fine - mutating the object, not the binding
console.log(config.retries); // 5Object.freeze prevents property mutation. Writes fail silently in sloppy mode and throw a TypeError in strict mode. Note that freeze is shallow - nested objects remain mutable.
"use strict";
const settings = Object.freeze({ timeout: 5000 });
settings.timeout = 1000; // TypeError: Cannot assign to read only propertyIn production
Teams that read const as "immutable" and treat a shared config object as safe to pass around are in for a surprise when two call sites mutate it concurrently. Deep immutability is a library concern - Immer for update workflows, structuredClone for a quick deep copy - or a TypeScript type concern (as const, Readonly<T>). The language keyword alone doesn't buy it.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free