Learn the basics of variable scope in javascript

Learn the basics of variable scope in javascript

In javascript, there are three types of scope: global, function, and block.

Prior to ES6, javascript only had global and function scope, so let's start with those two examples.

Function Scope

When a function is created that function creates its own local scope. Let's look at an example to review what this means:

const myFunction = () => {
    let myVariable = 'this is my value'
    console.log(myVariable)
}

console.log(myFunction())

// this is my value

This result is what we expected. We created a function and within that function, we declared a variable. When we logged that variable within the function (which we did on the very next line) we get the value logged in the console once the function is called.

Let us try something a little different.

const mySecondFunction = () => {
  let secondVariable = 'this is the second value'
}

console.log(secondVariable)

// Uncaught ReferenceError: secondVariable is not defined

The error we face is that the variable has been defined within our function, therefore it is not accessible outside of that function. It is function scoped. This result will be the same if you declare the variable with 'let', 'const', or 'var'.

Global Scope

When we create a variable outside of a function, we say that the variable has global scope. This means that the variable that we declared is accessible throughout the program. Here are a few examples:

let globalOne = 'global one value'

const globalTwo = 'global two value'

var globalThree = 'global three value'

Because these variables are within the global scope, it means we can do something like this:

const myGlobalFunction = () => {
  console.log(globalOne)
  console.log(globalTwo)
  console.log(globalThree)
}

myGlobalFunction()

// 'global one value'
// 'global two value'
// 'global three value'

Block Scope

As you work with creating global and function scoped variables, you might conclude that there are times that you have variables that end up in global scope that you would prefer they were not.

That problem was addressed in ES6 with the introduction of the 'let' and 'const' keywords. When we declare a variable using one of those keywords, we create a block-scoped variable.

Here we will create a block statement and look at an example to demonstrate what this means:

{
  const blockOne = 'block one value'
  console.log(blockOne)
  // block one value
}

{
  let blockTwo = 'block two value'
  console.log(blockTwo)
  // block two value
}

As demonstrated, when we try and access the variable inside the block, we are successful.

Let's try one more example:

{
  const blockThree = 'block three value'
}
console.log(blockThree)
// Uncaught ReferenceError: blockThree is not defined

{
  let blockFour = 'block four value'
}
console.log(blockFour)
// Uncaught ReferenceError: blockFour is not defined

In this example, when we try and access the variables outside of the block statement, we get the error because that variable is not defined. This is what block scope provides.

In my opinion, it is best practice to use 'const' when you can, 'let' when you need, and 'var' as little as possible. Let's look at one last example using the 'var' keyword.

{
  var blockFive = 'block five value'
}
console.log(blockFive)
// block five value

This result may come as a surprise. When using the keyword 'var' to declare a variable within a block, the variable is within the global scope. This means the variable can be accessed outside of the block it was declared, as we just demonstrated.

You may see the 'var' keyword used when you are reviewing legacy code bases, so it's important to understand these differences and why adding the 'let' and 'const' keywords in ES6 was so beneficial.