JavaScript Scope and Hoisting

Posted by Nolan Hughes on September 8th, 2018

Today I want to talk about two JavaScript concepts, scope and hoisting. Although two separate terms, they are related. I think an understanding of scope is probably best so that hoisting comes more naturally.

Scope

Scope determines the accessibility (visibility) of variables. Basically the scope of a variable determines how you access your variables throughout your JS files. There are three types of scope: global, function, and block. Lets go over the first two with some examples.

Global scope

var catName = "Melkor";
// code here can use catName, eg. console.log(catName)
myFunction = () => { // code here can also use catName, eg. alert(catName) }

Here we can see that the variable catName can be used anywhere.

Function scope

// code here can NOT use catName, eg. console.log(catName) would give us an error (ReferenceError: catName is not defined)
myFunction = () => { var catName = "Melkor"; // code here CAN use catName }
// code here can NOT use catName either

In this example, the variable catName can only be used in the function where it is declared.

The other type of scope is block and only deals with the JavaScript key words let and const. This is in the same vain as function scope but pertains to any blocks instead of just functions. Here are some examples.

var x = 10 if (1 === 1) { var x = 2 } console.log(x)

In this example it would log x as being 2 in the console.

let x = 10 if (1 === 1) { let x = 2 } console.log(x)

In this example it would log x as being 10 in the console. This is because redeclaring a variable inside a block will not redeclare the variable outside the block when using let instead of var.

Let vs. Const

The keywords let and const share many of the same properties except that const cannot be redeclared.

const PI = 3.141592653589793; PI = 3.14; // This will give an error

Const properties in objects or elements in a const array can be reassigned but not the whole array or object.

Hoisting

Declarations are hoisted to the top of the scope, assignments are not. Let it be known that the keyword var is the only one out of var, let, and const that is hoisted.

See the below examples and paragraphs for more explanation.

Example 1

console.log(y) var y = 7 // undefined

Example 2

console.log(y) // ReferenceError: y is not defined

Example 3

var y = 7 console.log(7) // 7

Example 1 would log as undefined. This is because var y (or the declaration) is being hoisted to the top so, console.log(y) sees that the variable is there but it just isn’t assigned to anything yet. If it didn’t see the variable y it would give us an error like in example 2.

To further this point, example 1 also isn’t saying that y = 7 because = 7 (or the assignment) isn’t hoisted by JavaScript. The console.log would have to be below the declaration and assignment of the variable, like in example 3.

Conclusion

Hopefully that shed some light on scope and hoisting in JavaScript. It’s a confusing subject but an extremely important one considering how many bugs can appear because of a lack of understanding.