Our Blog:

Understanding JavaScript Hoisting: A Comprehensive Guide for Better Coding


Middle
Andrej Vajagic

Andrej Vajagic

20.07.2023, 15:01

Read time: undefined mins

Understanding JavaScript Hoisting: A Comprehensive Guide for Better Coding

V8 (JavaScript engine)

You should read the previous blog first to get better insights before reading this.

But to recap: In JavaScript, an execution context is a concept that deals with the idea of scope or the environment in which code is evaluated and executed. It's the realm in which variables, functions, and objects are accessible. When JavaScript code runs, it does so within an execution context. Each execution context has three main components:

  • Variable Environment: This component consists of the variable and function declarations within the context. It is closely related to the concept of hoisting, as during the creation phase of an execution context, variable and function declarations are moved to the top of their respective environments.

  • Scope Chain: This component provides ordered access to variables based on their hierarchical nesting on the code. It consists of the variable object of the current context and the variable object of all its parents (lexical environment), forming a chain-like structure. The engine looks up the scope chain when trying to resolve identifiers (like variable names).

  • this Binding: This component refers to the value of this in the context. Depending on how a function is called, this can refer to different objects.

    • In the global context, this refers to the global object (like 'window' in a browser).
    • For a function, this depends on how the function is invoked - if it's called as a method of an object, this is the object;
    • if it's called as a regular function, this is the global object (or undefined in strict mode).
    • For arrow functions, this is lexically bound, meaning it's set to the this value of the outer function where the arrow function is defined.

Variable Environment in JavaScript:

The JavaScript Variable Environment is the area where variables are stored during the execution of a JavaScript program.

Each function in JavaScript has its own variable environment. When a function is invoked, a new execution context is created, and this new context will have its own variable environment, which is separate from other contexts.

The variable environment includes:

  • Local variables: Variables declared inside the function.
  • Arguments: The arguments with which the function was invoked.
  • This: A reference to the object that the function is a method of, or the global object if the function isn't a method of an object.

Now as we understand variable environment we can explain hoisting.

Hoisting:

Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their containing scope during the CREATION phase, before the code has been executed.

  1. Variable Hoisting:
    In JavaScript, a variable can be declared after it has been used. In other words, a variable can be used before it has been declared. This is possible because JavaScript engines hoist variable declarations to the top of the script or function.

    For example, the following code will work in JavaScript: code) Even though myVar is declared after it's logged to the console, JavaScript doesn't throw an error. Instead, it hoists the variable declaration var myVar; to the top of the scope, so the actual order of execution looks more like this: code)

    This is why myVar is undefined in the first log. The variable has been declared but not yet initialized with a value.

    One thing to note is that only the declarations are hoisted, not the initializations. If a variable is both declared and initialized at the same time as in var myVar = 5;, only the declaration var myVar; will be hoisted, not the initialization myVar = 5;.

  2. Hoisting with let and const:
    With ES2015 (let and const) hoisting works a bit differently. While declarations are still hoisted, the "Temporal Dead Zone" (TDZ) - a period from block start until declaration where they cannot be accessed - prevents their use until after their declaration has been initialized. This is why using a let or const variable before it's declared results in a ReferenceError. code) In the above example, myLetVar is still hoisted to the top of the scope, but it's not initialized with a value of undefined like var variables are. This means you'll get a ReferenceError if you try to use it before its declaration.

  3. Function declaration Hoisting:
    Just like variables, function declarations are hoisted to the top of their current scope. But unlike variables, function declarations are hoisted with their body. code)

    In the above example, even though the function myFunc is invoked before it is declared, the JavaScript engine doesn't throw an error. Instead, it hoists the entire function declaration to the top of the scope, so the actual order of execution is like this: code)

  4. Function expressions and arrow function Hoisting:
    Unlike function declarations, function expressions in JavaScript are not hoisted. This is because function expressions involve assigning an anonymous function (or a function with a name) to a variable, and the variable assignment is not hoisted, only the variable declaration is. Let's illustrate this with an example: code)

    In the above code, when we try to log myFunc before its definition, it returns undefined rather than the function or an error. This is because the variable myFunc is hoisted (i.e. the JavaScript engine is aware of its declaration), but its assignment as a function happens only where you've written it in the code, which is after the log statement.

    The same principle applies when using let or const: code) Here, because of the Temporal Dead Zone associated with let and const, trying to access myFunc before its definition results in a ReferenceError.

    Arrow functions, like function expressions, are not hoisted. This is because arrow functions are assigned to variables, and while variable declarations (let, const, var) are hoisted, their assignments are not. code) You get a TypeError because at the point where myFunc is invoked, myFunc is undefined due to hoisting, and trying to invoke (call with ()) undefined throws a TypeError.

Understanding hoisting can help you avoid potential bugs and errors in your code. It's generally considered good practice to declare and initialize your variables at the top of their scope to make it clear that they're available for use throughout that scope.

Share:

Accelerating Digital Success. Experience the future of web development – faster, smarter, better. Lets innovate together.

©2024 Dreit Technologies | All rights reserved

Contact

  • +38 64 577 3034
  • Serbia
  • Marka Pericina Kamenjara 11A, Ruma
  • Contact us