When writing codes, developers often encounter errors. When you execute a variable, function or class before actually initializing it, the code can output a different result other than what was expected or the JavaScript interpreter can throw an error and this can lead to developers spending a large amount of time trying to debug the code. In this article, you'll learn about JavaScript hoisting. A behavior peculiar to JavaScript.
Prerequisite:
Before proceeding with reading this article, you must have a basic understanding of JavaScript.
Table of contents
- What is hoisting
- Characteristics of JavaScript hoisting
- How variables are hoisted in JavaScript
- Function hoisting
- Function Declaration
- Function Expression
- Class hoisting
- How to use hoisting when coding
- Conclusion
What is Hoisting?
Hoisting in JavaScript refers to the behavior of the JavaScript interpreter to move the declaration of a variable, function, class or import to the top of the scope they were declared in before executing the code assigned to them.
Characteristics of Hoisting
Hoisting is a concept that does not occur in all programming language because in most programming language, the item must be declared before it is used otherwise there will be an error but JavaScript allows hoisting. Hoisting means the interpreter recognizes the declared data even though the data was not initialized at first.
Note: The data declared must be executed within the scope of declaration. In the latter sections, you'll have a better understanding of this concept.
The following are characteristics of JavaScript hoisting:
- A function can be used in a scope before the line the variable was declared
- A variable can be used before the referenced line, the interpreter throws an undefined and not an error
- The declaration of the variable can cause behaviorial changes in its scope before the line in which it is declared. Source: (MDN doc)
How variables are hoisted in JavaScript
There are three methods to declare variables in JavaScript: either using var, let or const. JavaScript hoists variables declared with each method differently. In this section you shall learn how JavaScript hoists the variables declared with these different methods.
Using var keyword
In hoisting, when var keyword is used to declare a variable, the JavaScript interpreter doesn't throw an error rather it returns undefined.
var myAge = 56;
console.log(myAge);
//56
console.log(myAge)
myAge = 56
//undefined
Consider these two code samples above, in the first code sample, 'myAge' was declared before it was used, and it gave an output but in the second code sample, 'myAge' was used before it was declared, it returned undefined.
In the second code sample, the JavaScript interpreter carried the declared 'myAge' variable to the top and returned undefined because when the interpreter carried the 'myAge' variable to the top, it assigned it to no value, because it was not initially declared first, thereby returning undefined.
The undefined that was returned by the JavaScript interpreter is not an error, rather it is an undefined string, which means that the JavaScript interpreter noticed that 'myAge' was declared but because it was executed before being declared, the JavaScript interpreter hoisted the 'myAge' variable but assigns it no value which made the interpreter return the variable as undefined. An undefined data is a data that was declared but not assigned to a value.
Now consider another code sample where the variable was not declared to check if JavaScript will throw an error or return undefined as in the previous code sample we looked at.
console.log(hisAge);
var myAge = 56;
//hisAge is not defined
The code above shows an 'hisAge' variable being used but not declared. The JavaScript interpreter goes through the entire global scope and doesn't find any variable declared as 'hisAge' so it throws an error saying 'hisAge is not defined'.
Note: The JavaScript interpreter will only hoist variables that are defined within the same scope of usage.
Using let keyword
When let keyword is used to declare a variable, JavaScript hoists the variable quite differently from that of the var keyword.
console.log(myAge);
let myAge = 56;
//Cannot access 'myAge' before initialization
Consider the above code sample where let was used to declare the variable. You'll notice that the JavaScript console displayed 'cannot access myAge before initialization'. This is because JavaScript knows that myAge variable was declared in the code but when the interpreter reads the code, it hoists 'myAge'and declares that we can't access it unless we declare it first. Unlike the var method of declaring variable, which returns undefined. Let method of declaring variables wouldn't return anything rather JavaScript had to let you know that you can't execute the variable unless you declare it first. This attribute of JavaScript is called Temporal Dead Zone. The Temporal Dead zone starts execution of the code at the beginning of the declared variable's scope and ends the code execution when the variable is declared using the let or const keyword.
Using const keyword
The const keyword used in declaring a variable is similar to using the let keyword except that when using const keyword, the variable cannot be assigned for another use. In terms of hoisting, JavaScript outputs the same result. Consider the code sample below.
console.log(myAge);
const myAge = 56;
//Cannot access 'myAge'before initialization
In the above code sample, JavaScript throws the same error it threw when we used the let keyword to declare our variable.
The Temporal Dead Zone is also applicable when using the const keyword.
Function Hoisting
In this section , you'll learn about two different ways of writing functions. Function expression and function declarations.
function declaration
declaredFunction(2,3)
function declaredFunction (a,b){
console.log(a+b)
}
//5
The above code sample contains a function that was declared before it was initialized. However, unlike variables, it neither returned undefined nor returned "cannot access before initialization", but why is that so?
It is because declared functions are not hoisted in JavaScript. You can execute a function in JavaScript before it's initialization wihin the same scope.
This type of functions that are executed before use in JavaScript are called, declared functions. In the next section, you shall learn about expressed functions which can be hoisted in JavaScript.
But before learning about expressed functions, consider the following code samples.
oneScope()
anotherScope()
function oneScope(){
function anotherScope(){
console.log('this is another scope')
}
console.log('this is one scope')
}
//this is one scope
//anotherScope is not defined
In the above code sample, both oneScope() and anotherScope() were called before initialization but oneScope() was executed while anotherScope() wasn't, the reason is because oneScope() was called in the same scope where it was initialized while anotherScope() was initialized in another scope. But consider the following code sample:
oneScope()
function oneScope () {
anotherScope ()
function anotherScope () {
console.log('this is another scope')
}
console.log('this is one scope')
}
In the above code sample, anotherscope() was defined in the same scope of initialization and it gave the expected output.
Function Expression
Consider the following code samples, expressedFunction() was called before it's initialization, but JavaScript console threw an error, because JavaScript interpreter sees expressed functions just like variables when hoisting.
expressedFunction ()
let expressedFunction = function () {
console.log('this is an expressed function')
}
//Cannot access 'expressedFunction' before initialization
let expressedFunction = function () {
console.log('this is an expressed function')
}
expressedFunction ()
//this is an expressed function
Class Hoisting
Consider the following code sample:
console.log(new jonathanProfile(42, 'Norway'))
class jonathanProfile {
constructor(age, country) {
this.age = age;
this.country = country;
}
}
//Cannot access 'jonathanProfile' before initialization
In the code sample above, JonathanProfile class was called before initialization JavaScript threw the same reference error, it threw at let, const and expressed functions.
From the above code sample, you'll realize that JavaScript interpreter knew that that JonathanProfile class was initialized later in the code but because it was not declared initially, JavaScript had to throw a reference error.
The code below shows the code written in the correct order.
class jonathanProfile {
constructor (age, country) {
this.age = age;
this.country = country;
}
}
console.log(new jonathanProfile (42, 'Norway'))
//jonathanProfile {age: 42, country: 'Norway'}
In the above code, the JonathanProfile class was initialized before it was called.
Conclusion
It's important to know the behavior of each data type when executing a code, now that you're familiar with how JavaScript interpreter hoists codes, you'll write better codes and know the reason behind some of the bugs you encounter when coding.
Please do well to leave a like and a comment
Top comments (0)