var, let and const — and why var is retired
Module 1 used const and let without explaining either. Time to fix that —
and to deal with var, which you will see in every third tutorial online and
should almost never write.
Storing a value
A variable is a name for a value:
const ratePerPlate = 80;
const customer = 'Priya';
let platesToday = 3;
console.log(`${customer} ordered ${platesToday} plates at ₹${ratePerPlate}`);
Priya ordered 3 plates at ₹80
Three parts: the keyword (const or let), the name, and the value. The
semicolon at the end is optional in JavaScript but include it — the rules for
when you can omit it have sharp edges, and every team you join will use them.
const by default, let when you must
The difference is whether the name can be pointed at a different value later.
let plates = 3;
plates = 5;
console.log(plates);
5
Fine. Now with const:
const plates = 3;
plates = 5;
TypeError: Assignment to constant variable.
Use const unless you know you need to reassign. Not because reassignment is
wicked, but because const tells the next reader — usually you, in three months —
that this name means one thing all the way down the function. That is one less
thing to hold in your head while reading.
In practice most declarations end up const. When you genuinely need to
accumulate or swap a value, reach for let.
The trap: const does not mean the contents cannot change
This one catches nearly everyone, and it catches them in a confusing way.
const items = ['dal'];
items.push('sugar');
console.log(items);
[ 'dal', 'sugar' ]
No error. The array changed.
const order = { plates: 3 };
order.plates = 5;
console.log(order);
{ plates: 5 }
Also no error.
const protects the binding, not the value. It means "this name will always
point at this same array" — and that promise is kept. The array itself is a
separate thing, and nothing stopped you rearranging what is inside it.
Try to repoint the name and const does its job:
const items = ['dal'];
items = [];
TypeError: Assignment to constant variable.
So const gives you no protection against a function quietly modifying an array
you passed it. That is a real problem, and module 4 deals with it properly. For
now, know that const is a weaker guarantee than the name suggests.
var, and the bug it gives you for free
var is the original way to declare a variable, from 1995. It still works, and
it will never be removed, because removing it would break a large part of the
web. It is nonetheless retired, and here is why.
Run this:
for (var i = 0; i < 3; i++) {
// nothing here
}
console.log(i);
3
The loop counter is still alive after the loop finished. It was never meant to leave. Worse:
if (true) {
var leaked = 'yes';
}
console.log(leaked);
yes
A variable declared inside an if block is visible outside it.
With let, both of these behave sensibly:
if (true) {
let hidden = 'no';
}
console.log(hidden);
ReferenceError: hidden is not defined
The reason is a single design decision. var is scoped to the whole enclosing
function; let and const are scoped to the nearest block — the nearest pair
of curly braces. Every other language you are likely to meet uses block scoping,
and so does the rest of JavaScript's own syntax, which is why var feels wrong
even before you can say why.
Why does the leak matter in real code? Because names collide silently. A var i
in a loop and a var i forty lines down in the same function are the same
variable, and one quietly overwrites the other. That bug does not announce
itself; it just produces a wrong number.
var has two more problems, both covered properly in module 3:
- It can be re-declared.
var total = 1; var total = 2;is accepted, so a duplicated name is not an error. - It is hoisted as
undefined, so using it before its line gives youundefinedrather than an error.letandconstgive you aReferenceErrorinstead, which is much more useful.
The rule: const by default, let when you must reassign, var never.
When you meet var in older code, that is your signal the code predates 2015 —
and possibly its advice does too.
const |
let |
var |
|
|---|---|---|---|
| Scope | Block | Block | Function |
| Reassign the name | No | Yes | Yes |
| Re-declare the name | No | No | Yes |
| Before its line | ReferenceError |
ReferenceError |
undefined |
| Use it | By default | When reassigning | Never |
Naming
Names are camelCase — first word lowercase, later words capitalised:
ratePerPlate, customerName, totalPaise. Not rate_per_plate, which is
Python's convention, and not RatePerPlate, which JavaScript reserves for
classes.
Rules the language enforces: start with a letter, _ or $; no spaces; no
reserved words like class or return. Names are case-sensitive, so total
and Total are two different variables — a genuinely common typo.
Conventions worth adopting:
- Say what it holds.
platesTodaybeatsp, andxshould be reserved for an actual coordinate. You will read this code far more often than you write it. - Booleans read as questions.
isPaid,hasDelivered,canCancel. UPPER_SNAKE_CASEfor fixed configuration that never changes at run time:const RATE_PER_PLATE = 80;. This is a convention among programmers, not a rule the language knows about.- Keep units in the name when there is any doubt.
totalPaiseandtotalRupeescannot be confused; two variables both calledtotalcan, and that is a bug worth a hundred rupees a time. Module 6 goes further into why money should be counted in paise.
Check your work
const plates = 3; plates = 5; gives TypeError: Assignment to constant variable. The name cannot be repointed.
const items = ['dal']; items.push('sugar'); works, and items is
[ 'dal', 'sugar' ]. No error, because const protects the binding and not the
contents. items = [] on the same array is an error — the difference is
whether you are changing the name or the thing.
for (var i = 0; ...) then console.log(i) after the loop prints 3. With
let it is ReferenceError: i is not defined, because let is scoped to the
loop's block and the name does not exist outside it.
var leaked inside an if block is readable outside it, printing yes.
let hidden in the same place gives ReferenceError: hidden is not defined.
var is scoped to the function, let to the block.
Which keyword for a running total inside a loop? let — it is reassigned on
every iteration. For the rate it is multiplied by, const.
const total = 1; const total = 2; is SyntaxError: Identifier 'total' has already been declared. The same two lines with var are accepted silently,
which is the third reason var is retired.
Practice
- Declare
constfor a customer name and a rate, andletfor a plate count. Print a line using a template literal. Then change the plate count and print again. - Try to reassign the
constand read the error. Say what the word "constant" is actually promising before you move on. - Prove
constis weaker than it sounds. Make aconstarray,pushto it, and print it. Then try assigning a whole new array to the same name. Explain to yourself why one is allowed and the other is not. - Do the same with a
constobject: change a property, then try to replace the whole object. - Cause the
varleak deliberately. Write thefor (var i ...)loop and logiafterwards. Then changevartoletand read the error. This is the single clearest demonstration of the difference, and it is worth typing rather than reading. - Write a function-length piece of code with
var iin two separate loops and convince yourself they are the same variable. Then fix it withlet. - Rename badly on purpose: take working code and change every variable to
a,b,c. Read it back after five minutes. This is the argument for good names, and experiencing it once is more persuasive than being told. - Declare
const RATE_PER_PLATE = 80and alet total, then compute the cost of 3, 5 and 2 plates in a loop. Decide for yourself which names deserveconst.
Next: types — what a value actually is, and why "5" + 2 gives you "52"
while "5" - 2 gives you 3.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship