Complete Intro Modern Javascript
Variables And Scopes
This is still a work in progress. New content is synced here as it gets ready.

Block Scopes and the var/let/const keywords

Here’s one of my favorite JavaScript trick questions. Is the following a valid JavaScript line of code?

{{{}}}

If you open up your dev-tools console and paste the line above, what will happen?

mjs2
Why is this valid??

Nothing. No error. It’s valid!

So now the question is: What did it do? (It did not create any objects 😎)

Block Scopes

These curly brackets are just nested block scopes. We could write code in them:

mjs3
JavaScript does not care about spacing

A block scope is created with a pair of curly brackets. This happens every time you create an if-statement, for-statement, while-statement, etc. The only exception is the curly brackets you use with functions. These create a function scope, not a block scope.

{
  // Block Scope
}
if (true) {
  // Block Scope
}
for (var i = 1; i <= 10; i++) {
  // Block Scope
}
function doSomething() {
  // Function Scope
}

So what exactly is the difference between a block scope and a functions scope you ask?

var vs let

Function scopes are created for each function (like doSomething above). One difference they have from block scopes is obvious when using the var keyword.

Variables defined with var inside a function scope are okay; they don’t leak out of that scope. If you try to access them outside of the scope, you can’t:

mjs4
As expected

However, when you define variables with var in a block scope you can totally access them outside that scope afterward, which is a bit problematic.

For example, in the standard for-loop statement above, v is defined with var. So guess what you can do AFTER the loop?

mjs5
A famous WTF-JavaScript

This is why the more recommended way to declare variables in modern JavaScript is by using the let keyword instead of the var keyword. When defining variables with let, we won’t have this weird out-of-scope access problem.

mjs6
Much Better

Take-away: Use the let keyword to define variables. BUT, only when the variable NEEDS to CHANGE its value. This should not be a common thing in your code.

Here’s what you can mark as a better practice:

Always use the const keyword to define variables. Only use the let keyword when you absolutely need it. Never use the var keyword.

Okay… What exactly is const?

const all-the-things

In JavaScript, a variable is basically a label we put on a certain space in the computer’s memory.

let V = {id: 42}; // create a memory unit and label it as V

When you change the value of the variable V, you’re not changing the content of the memory space that was initially associated with V. You’re creating a new memory space and changing the V label to be associated with this new space.

V = []; // No errors

// Discard current memory unit (and its current label)
// Create new memory unit and label it as V

When you use const to define a variable you are instructing the computer to not only label a space in memory but to also NEVER CHANGE that label. The label will be forever associated with its same space in memory.

const V = { id: 42 };

// Create a memory unit and label it as V
// This label cannot be discarded or reused

// Later in the program
V = []; // TypeError: Assignment to constant variable.

Note that the constant part here is just the label. The value of what’s in the memory space can still change (if it’s mutable). For example, objects in JavaScript are mutable, so for the V above:

// You can do:
V.id = 37; // No errors

console.log(V.id) // 37

// But you still can't do:
V = { id: 37 }; // TypeError: Assignment to constant variable.

This applies to arrays too (because they are mutable as well).

Strings and Integers are immutable in JavaScript so the only way to change a string or integer value in JavaScript is to discard current memory space and re-label another one. That’s why if you have a numeric counter you need to increment in your program you would need to use let:

// Can't use const for this case:
let counter = 0;
counter = counter + 1; // Discard and re-label

If you need a variable to hold a changing scalar value (like the counter example above) then using let is okay. However, for most other cases it’s probably much better for you to stick with using const for all your variables.