Lexical Variable Scoping with Javascript

Lexical scoping means that the scope of a variable is determined by where it is defined in the source code — specifically, by the block or function it is written inside. In Javascript, code blocks are created using curly braces ({}). For example:

function someFunction() {
    // some code here
}

function anotherFunction() {
    // some more code here
}

someFunction and anotherFunction are two different code blocks. These two different code blocks could also be considered as two different scopes. What that means is that the variables declared in someFunction only affect that block of code, and those declared in anotherFunction only affect that block of code. They are "scoped" in that sense.

To illustrate:

var name = "Kenny"

function someFunction() {
    var name = "Kyle"
    console.log("someFunction block:", name) // someFunction block: Kyle
}

function anotherFunction() {
    var name = "Timmy"
    console.log("anotherFunction block:", name) // anotherFunction block: Timmy
}

console.log("global", name) // global Kenny

As you can see, the same variable name retains its global value although it gets redefined within someFunction and anotherFunction.

Now here is where it can get a bit tricky. With that knowledge in mind, it is easy to assume that this would always be the case whenever we have code blocks. Except, it doesn’t work the same with if/else statements and for loops.

var name = "Kenny";

if (name) {
  var name = "Kyle";
  console.log("if block:", name); // if block: Kyle
}

console.log("global", name); // global Kyle

The name variable inside the if block resets the value of name. The same happens in a for loop:

var name = "Kenny";

for (var i = 0; i < 1; i++) {
  var name = "Kyle";
  console.log("for loop block:", name); // for loop block: Kyle
}

console.log("global", name); // global Kyle

The solution is to use the let keyword instead of var.

var name = "Kenny";

if (name) {
  let name = "Kyle";
  console.log("if block:", name); // if block: Kyle
}

console.log("global", name); // global Kenny
var name = "Kenny";

for (var i = 0; i < 1; i++) {
  let name = "Kyle";
  console.log("for loop block:", name); // for loop block: Kyle
}

console.log("global", name); // global Kenny
Tags: