Hoisting

In many languages, variables and functions have to be declared upfront before they can be used later in code. Attempting to use them before declaration would result in an error.

In JavaScript, it's possible to use variables and functions before they're explicitly declared later in code. This feature of JavaScript is called Hoisting. In a sense, the declarations are "hoisted" to the top of the code.

While hoisting is a useful feature, in the interest of code readability and maintenance, it's perhaps a good practice to put declarations before they're used.

Discussion

  • Could you illustrate hoisting with an example?
    Example showing hoisting in global context and function context. Source: Agrawal 2017.
    Example showing hoisting in global context and function context. Source: Agrawal 2017.

    In the code console.log(x); var x = 1;, the variable x is used before it's declared. JavaScript allows this because of hoisting.

    Hoisting is also possible for functions. In the code add(3, 4); function add(a, b) { return a + b; }, the function add() is called before it's declared. Again, this is possible due to hoisting.

    Hoisting can occur in any execution context. JavaScript has three types of execution contexts: global, function, and eval.

  • Is hoisting moving a declaration to the top of the scope?
    Execution context has a creation and an execution phase. Source: Adapted from McGinnis 2018.
    Execution context has a creation and an execution phase. Source: Adapted from McGinnis 2018.

    One common (and incorrect) explanation of hoisting is that the JavaScript engine moves variable and function declarations to the top of their scope. Variable declarations are initialized with value undefined. In reality, the JavaScript engine doesn't move code to the top this way.

    The correct explanation lies in understanding execution context. This is the environment in which the code runs. Such an environment encapsulates this, variables, objects and functions that are accessible. Execution context is created in two phases: creation phase and execution phase.

    During the creation phase, memory is allocated for variables and functions in that scope. The entire function body is in memory but it's not executed. Likewise, variables become available in memory but are not initialized. It's only later, during the execution phase, that initializing variables and calling of functions happen.

  • What can be hoisted?

    Variables and functions are hoisted. Functions can be called earlier in the code even if their declarations happen later. It's interesting to note that if a variable and a function have the same name (a practice that should be discouraged), variable initialization takes precedence over function declaration. If the variable in uninitialized, function declaration takes precedence.

    Function expressions are not hoisted. Function expressions take the form var a = function () {...}. Variable a is hoisted, which means that it's initialized to undefined. Thus, we can't make the call a() since the variable is not initialized with the function object. Similarly, arrow functions, which are of the form var a = () => ..., are not hoisted.

    Class declarations are "hoisted" only in the sense that memory is allocated but not initialized with the class object. With class expressions, the variable is hoisted but it's initialized to undefined. For example, var Square = new Polygon(); var Polygon = class { ... } won't work because Polygon is undefined. This effectively means that we can't instantiate objects without putting the declaration first.

  • Could you share more details on hoisting variables?
    Firefox Developer Tools showing hoisting of different variables. Source: Devopedia 2020.
    Firefox Developer Tools showing hoisting of different variables. Source: Devopedia 2020.

    JavaScript has this default behaviour that a variable initialized without a declaration is automatically declared with global scope. This happens during the execution phase of execution context, not during the creation phase. Therefore, such variables are not hoisted. Hoisting applies only to explicitly declared variables. For example, hoisting works for console.log(a); var a = 1; but not for console.log(b); b = 1;. For this reason, it's recommended to explicitly declare variables.

    Variables declared with keywords let or const are "hoisted" in the sense that memory is allocated during the creation phase of execution context. Thus, during execution phase, JavaScript engine won't complain that they're undefined. However, the engine will still throw a reference error when the code attempts to use them before they're properly initialized. Unlike the var keyword, let and const keywords don't initialize variables with undefined. The solution is therefore to declare before using such variables. Hoisting is not useful for let and const.

Milestones

1995

JavaScript is announced as a dynamic scripting language that can run within a web browser. Two years later, a more standardized form of JavaScript, called ECMAScript is published by ECMA International.

Oct
2010

A video on YouTube explains JavaScript hoisting with examples. This shows that the term "hoisting" is in use by 2010, if not earlier.

Jun
2015

ECMA International releases ECMAScript® 2015 Language Specification. This specification uses the term "hoisting". It's said that prior standards didn't use the term explicitly. Hoisting provides us a metaphor to think about execution contexts.

Sample Code

  • // Source: https://www.javascripttutorial.net/javascript-hoisting/
    // Accessed 2020-10-06
     
    // Can access variable but it's undefined
    // Only declaration is hoisted, not the initial value
    console.log(counter);
    var counter = 1;
     

References

  1. Agrawal, Yash. 2017. "Hoisting in JavaScript." Codeburst.io, on Medium, August 2. Accessed 2020-10-06.
  2. Codecademy. 2016. "[JavaScript Tutorial] 008 JavaScript The Execution Context Creation and Hoisting." Codecademy, via YouTube, April 2. Accessed 2020-10-06.
  3. ECMA International. 2015. "ECMAScript® 2015 Language Specification." Standard ECMA-262, 6th Edition, ECAM International, June. Accessed 2020-10-06.
  4. Franco, Jerome. 2019. "Myth about JavaScript Hoisting." Medium, May 10. Accessed 2020-10-06.
  5. JavaScript Tutorial. 2020. "JavaScript Hoisting." JavaScript Tutorial. Accessed 2020-10-06.
  6. MDN Web Docs. 2020. "Hoisting." MDN Web Docs, Mozilla, September 14. Accessed 2020-10-06.
  7. McGinnis, Tyler. 2018. "The Ultimate Guide to Hoisting, Scopes, and Closures in JavaScript." Ui.dev, October 13. Accessed 2021-02-03.
  8. Mishra, Rupesh. 2017. "Execution context, Scope chain and JavaScript internals." Medium, May 19. Accessed 2020-10-06.
  9. Tuts+ Code. 2010. "JavaScript Hoisting Explained." Tuts+ Code, on YouTube, October 7. Accessed 2020-10-06.
  10. Wakio, Mabishi. 2020. "Understanding Hoisting in JavaScript." Tutorial, Digital Ocean, September 15. Accessed 2020-10-06.
  11. Wikipedia. 2020. "JavaScript." Wikipedia, September 29. Accessed 2020-10-07.

Further Reading

  1. JavaScript Tutorial. 2020. "JavaScript Hoisting." JavaScript Tutorial. Accessed 2020-10-06.
  2. James, Mike. 2013. "JavaScript Hoisting Explained." i-programmer.info, January 23. Accessed 2020-10-06.
  3. Tuts+ Code. 2010. "JavaScript Hoisting Explained." Tuts+ Code, on YouTube, October 7. Accessed 2020-10-06.
  4. Codecademy. 2016. "[JavaScript Tutorial] 008 JavaScript The Execution Context Creation and Hoisting." Codecademy, via YouTube, April 2. Accessed 2020-10-06.
  5. Agrawal, Yash. 2017. "Hoisting in JavaScript." Codeburst.io, on Medium, August 2. Accessed 2020-10-06.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
4
0
696
795
Words
1
Likes
2638
Hits

Cite As

Devopedia. 2021. "Hoisting." Version 4, February 3. Accessed 2024-06-26. https://devopedia.org/hoisting
Contributed by
1 author


Last updated on
2021-02-03 05:49:31
  • JavaScript
  • JavaScript Data Types
  • JavaScript Function Expression
  • JavaScript Fetch
  • JavaScript Events
  • ECMAScript