Skip to content

Instantly share code, notes, and snippets.

@maxogden
Last active Jun 21, 2022
Embed
What would you like to do?
JS hoisting by example

JavaScript function hoisting by example

Below are many examples of function hoisting behavior in JavaScript. Ones marked as works successfuly print 'hi!' without errors.

To play around with these examples (recommended) clone them with git and execute them with e.g. node a.js

Notes on hoisting

(I may be using incorrect terms below, please forgive me)

When JS is parsed, a first pass is done over each scope, and function definitions are immediately discovered. An example of a function definition is function foo() {}. When a function is declared like this, with a name, that name becomes available to the entire scope when the code in that scope is executed.

A crude timeline of how JS gets executed:

  1. Parse the scope and detect all function definitions
  2. Execute the code top-to-bottom with all functions found in step 1 available as variables

This behavior is called 'hoisting' because it is almost like the function definitions have been 'hoisted' up to the top of the function.

Assignments are not evaluated until the code is executed. An example of an assignment is var foo = function() {} or var foo = function foo() {}. A function must not be associated with an assignment in order for it to be hoisted (see example L)

Wrapping a function in parenthesis (()) is a quick way to convert a function definition into a function expression, which means it does not get hoisted (similar to assigning the function to a variable). I personally do not use this pattern regularly as I find it overly confusing to newbies etc, but I have included it because it is widely used in e.g. jQuery plugins.

I use hoisting as a code organization tool, for example here I rely on hoisting to make parseStream() available on line 20, even though it is defined on line 41, which I think makes that file more readable as I can put the 'meat' of the function at the top.

// A (works)
function sayHi() {
console.log('hi!')
}
sayHi()
// B (works)
sayHi()
function sayHi() {
console.log('hi!')
}
// C (works)
var sayHi = function() {
console.log('hi!')
}
sayHi()
// D (does not work)
sayHi()
var sayHi = function() {
console.log('hi!')
}
// E (does not work)
(function sayHi() {
console.log('hi!')
})
sayHi()
// F (does not work)
sayHi()
(function sayHi() {
console.log('hi!')
})
// G (works)
(function sayHi() {
console.log('hi!')
})()
// H (works)
(function() {
console.log('hi!')
})()
// I (works)
var sayHi = (function() {
console.log('hi!')
})()
// J (works)
var sayHi = (function() {
console.log('hi!')
})
sayHi()
// K (does not work)
sayHi()
var sayHi = (function() {
console.log('hi!')
})
// L (does not work)
sayHi()
var x = function sayHi() {
console.log('hi!')
}
// M
var x = (function sayHi() {
console.log('hi!')
})
x() // works
sayHi() // does not work
@RecDev
Copy link

RecDev commented Jan 22, 2017

Great! Thanks for sharing.

@nturbanov
Copy link

nturbanov commented Jan 24, 2017

Any reason why you wrapped the function is parenthesis in m.js?

@machsx
Copy link

machsx commented Mar 16, 2017

Nice to have all such examples gathered here. Thanks!

@Rrrapture
Copy link

Rrrapture commented Apr 4, 2017

@sunnykgupta thanks for the Speaking JS link. Looking at the free online edition now. :)

@englishextra
Copy link

englishextra commented Apr 7, 2017

Add my two cents:

var a = function () {
	b();
	c();
},
b = function () {
	alert("b");
},
c = function () {
	alert("c");
};

a();

jsfiddle

@aloerina01
Copy link

aloerina01 commented Apr 27, 2017

👍

@alexnlfm
Copy link

alexnlfm commented May 16, 2017

Very useful tutorial! Thanks a lot!

@zimejin
Copy link

zimejin commented May 22, 2017

JavaScript is so wild.

@levarne
Copy link

levarne commented Jul 25, 2017

👍 leka man

@DanChab
Copy link

DanChab commented Aug 6, 2017

awesome...

@HimmelsturmerIX
Copy link

HimmelsturmerIX commented Sep 7, 2017

why e.js does not work?

@Ghanshyam-K-Dobariya
Copy link

Ghanshyam-K-Dobariya commented Jan 5, 2018

superb.... great things explained in easiest way...

@tienthanhjlw
Copy link

tienthanhjlw commented Jan 25, 2018

Thanks :)

Copy link

ghost commented May 16, 2018

i.js is somewhat misleading, in that sayHi does not get assigned a function like in the rest of cases, but the execution result. It would be clearer if the variable had some name other than sayHi in that case (e.g. x, as in l.js and m.js).

@mohamedhafezqo
Copy link

mohamedhafezqo commented May 28, 2018

👍

@Clburguete
Copy link

Clburguete commented Jun 7, 2018

Great. Thanks!

@RajkamalSR
Copy link

RajkamalSR commented Nov 16, 2018

Great examples. Thanks ;)

@BDGrace
Copy link

BDGrace commented Jun 5, 2019

Is this outdated now? Looks like at least most of the not working examples work in the console....

@maxogden
Copy link
Author

maxogden commented Jun 5, 2019

@BDGrace you have to clone this repo and run the examples with node <x>.js since the devtools console works differently in regards to hoisting logic

@Josfrax
Copy link

Josfrax commented Jul 1, 2019

Great! Thanks for sharing.

@manasdwd07
Copy link

manasdwd07 commented Dec 11, 2019

Great explanation ! Thanks alot :)

@IvanDerlich
Copy link

IvanDerlich commented May 2, 2020

Excelent explanaition!

@iravinandan
Copy link

iravinandan commented May 9, 2020

cool.
Function declarations are hoisted but not function expressions.

@tim-andes
Copy link

tim-andes commented Jun 8, 2020

something shorter could be:
var sayHi = !function() { console.log('hi!') }();
or this:
var sayHi = (() => console.log('hi!'))();

Doesn't this remove the 'hoisting' aspect, though?

@heytulsiprasad
Copy link

heytulsiprasad commented Sep 4, 2020

Great examples!

@colpachi
Copy link

colpachi commented Oct 25, 2020

Thx for sharing !

@bantya
Copy link

bantya commented Mar 5, 2021

AMZNG!.

@LeonardoLGDS
Copy link

LeonardoLGDS commented Sep 22, 2021

Thanks for the content!

@ggchicote
Copy link

ggchicote commented Feb 12, 2022

Thanks for sharing!

@citizen46
Copy link

citizen46 commented Apr 7, 2022

#Suggestion.

You can make a link to it, "see example L" as.

see example L

URL: https://gist.github.com/maxogden/4bed247d9852de93c94c#file-l-js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment