Understanding How Hoisting Works in JavaScript



Hoisting is a JavaScript mechanism that lets you access variables and functions before you initialize them. Hoisting such a declaration effectively moves it to the top of its scope.


Learn all about how hoisting works in JavaScript and how to manage it best to avoid errors in your code.


Hoisting Variables With var, let, and const

Hoisting is possible because JavaScript uses the JIT (Just-in-Time) compilation system, which scans your code to identify all variables in their respective scopes.

The JIT compiler then hoists all instances of variable declarations to the top of their scope upon compilation. JavaScript only hoists declarations of variables, not their initializations.

The behavior of variables, when hoisted, depends on the keyword you declare them with, as each keyword behaves differently.

var

Accessing an uninitialized variable declared with the var keyword will return undefined. For example:

console.log(foo);  
var foo = 2;

The above code logs undefined because it calls console.log before it initializes the variable.

The JavaScript compiler views the previous code block like so:

var foo;
console.log(foo);
foo = 2;

During hoisting, variables obey the rules of JavaScript scoping. Javascript will only hoist a variable to the top of the scope you declared it in. Attempting to log the value of a variable outside its declared scope will result in a ReferenceError. For example, if you declare a variable inside a function, it won’t be visible outside that scope:

function myFunction() 
console.log(foo);
var foo = 10;

myFunction();
console.log(foo);

Trying to access a variable outside its scope will result in a ReferenceError.

let and const

According to the MDN documentation on let and const hoisting, JavaScript also hoists variables declared with the let and const keywords. However, unlike variables declared with the var keyword, they are not initialized with an undefined value.

For example:

function myFunction() 
console.log(foo);
console.log(bar);
console.log(baz);

var foo = 5;
let bar = 10;
const baz = 15;

myFunction();

You cannot access variables declared with the let and const keywords before initializing them with a value.

Hoisting Functions

JavaScript hoists functions similarly to variables. As with variables, it depends on how you declare them. For example, JavaScript hoists function declarations differently from function expressions.

A function declaration is a function declared with a name, while a function expression is a function whose name you can omit. For example:

function foo() 

const bar = () =>

JavaScript hoists function declarations but not function expressions. For example:

foo(); 
bar();


function foo()
console.log(5);


var bar = function expression()
console.log(10);
;

This code calls foo before declaring and initializing it as a function, but it still logs 5 to the console. However, trying to call bar results in a TypeError.

Managing Hoisting

Being aware of hoisting and the potential errors that could occur if managed wrongly can save you long hours of debugging. Here are some ways you can manage hoisting.

Declare Variables Inside Functions

Declare variables inside the functions that will access them. You won’t always be able to do this, as you may need a global variable that you can access within multiple functions. So ensure that you only declare variables globally if you really need to.

Declare Variables With let or const

You should always use the let and const keywords in place of the var keyword when declaring variables. This practice is beneficial when declaring local variables inside a function. Knowing the proper ways to declare variables in JavaScript reduces the chances of errors caused by hoisting occurring in your code.

Declare Variables at the Top of Their Scope

Declare all your variables at the top of their respective scopes, before any other statements. Doing so will ensure the JavaScript compiler does not have to hoist those variables to access them.

Using Strict Mode

Strict mode is a JavaScript mode that regulates poor syntax, optimizes the run time of your code, and prohibits abuse of JavaScript’s loosely typed syntax by throwing errors at compile time.

For example, in “sloppy mode,” due to hoisting, you can access a variable outside of the initialized function, even though it wasn’t declared:

myFunction();
console.log(foo);

function myFunction()
foo = 20;

In the code block above, JavaScript automatically declares foo and hoists it to the top of the global scope, ignoring the scope you initialized it in.

You can use strict mode to fix this behavior and throw an error if you try accessing the variable outside its function scope.

Strict mode does not stop hoisting altogether. Instead, it prevents the most confusing and error-prone forms of hoisting. It’s still important to understand the general concept and the rules behind hoisting, even when using the strict mode safety net.

To opt into strict mode at a global level, declare the syntax at the top of your script file:

"use strict"; // or 'use strict'

To opt into strict mode at a function level, declare the syntax at the top of a function body before any statements:

function myStrictFunction() 
"use strict";

If you declare strict mode at a function level, the setting will apply only to statements inside that function.

Declaring strict mode at a global level prevents variables from being accessed outside their respective scopes:

"use strict";
myFunction();
console.log(foo);

function myFunction()
foo = 20;

With strict mode turned on, the JavaScript compiler will hoist myFunction() to the top of its scope without the undeclared variable.

Understand What Affects Hoisting

Hoisting is quite unique to JavaScript and can be a very confusing behavior to wrap your head around. It can affect variables and functions, but there are ways to prevent it if you need to.

Several factors can affect hoisting, so it is best to avoid any occurrence of variable or function hoisting in your code.


Source link

Leave a Reply

Your email address will not be published. Required fields are marked *