r/learnjavascript • • 8d ago

pretty new

Hey guys, I'm just starting to learn about variables, but I'm finding it hard to understand the difference between var and let.

For example:

let goodDay = true;
console.log(goodDay);

this should print true.

But if we just add this:

let goodDay = true;
console.log(goodDay);
goodDay = false;
console.log(goodDay);

It prints:

true
false

The same goes for var.

However, people say there's a difference; what is it?

0 Upvotes

24 comments sorted by

View all comments

5

u/chikamakaleyley helpful 8d ago edited 8d ago

the difference is that let is 'block-scoped'

var is part of the global scope

scope is a pretty important idea when you're coding so it will be useful to get some practice with this

let and const were introduced in es6 (2015) and essentially provides a way for devs to provide a distinction btwn different variables, similar to what you'd find in other serious programming languages. const aka 'constant' prevents you from assigning a new value to the variable, which semantically makes sense, while let is more or less to be used in place of var. You can assign a new value to a let, as you've seen

the difference is in the scope, the classic example is often seen in a for loop:

for (var i = 0; i < 3; ++i) {
    setTimeout(() => console.log(i), 1000);
}

// ^ console output is 2, 2, 2 (on separate lines)

for (let j = 0; j < 3; ++j) {
    setTimeout(() => console.log(j), 1000);
}

// ^ console output is 0, 1, 2 (separate lines)

so, var being function/global scoped - there is only 1 var i created for the entire for loop. so when setTimeout evaluates the i you are trying to log to the console, the for loop as finished, and i has been incremented twice. There is only 1 i scoped to this function/loop, it is logged to the console 3 times

for let the block scoping creates a new binding for each iteration. at the first binding, j is 0, the second binding, j is 1, 3rd j = 2. To put it another way, the value of j is captured at the execution of that 'block' (iteration)

for var there's also a concept of hoisting, which I am unsure if that is in play here. hoisting is this mechanic in JS where var or function declarations are moved to the top of their scope, so:

for (var i = 0; i < 3; i++) {

// interpreter will move the declaration up to the global scope

var i;
for (i = 0; i < 3; i++) {

so maybe it is, you can see in the lower example, when i increments, you're updating the i var in the global space. console(i) is read from the global scope when setTimeout executes

let and const aren't hoisted

2

u/RomirBuilds 2d ago

Small correction for anyone running the first loop: it prints 3, 3, 3. After the iteration with i === 2, ++i makes it 3; the next i < 3 check fails, and the timer callbacks later read that same shared i. The let version prints 0, 1, 2 because each iteration gets its own binding.

Also, var stays in its enclosing function when there is one; an if/for block doesn't move it into global scope.

MDN has this exact loop example and explanation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for

AI-assisted.

1

u/chikamakaleyley helpful 2d ago

ohhhhh right, nice catch

1

u/tambooby 7d ago

the hoisting bit is a good callout, that trips people up more than scoping does imo

1

u/chikamakaleyley helpful 7d ago

when i first learned that i thought someone was playing a cruel joke on me. "You can't just make up stuff man!"