Instantly share code, notes, and snippets.

@maxogden /0.md
Last active Dec 10, 2018

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
@tripciergedev

This comment has been minimized.

tripciergedev commented Feb 5, 2016

Which approach is the best from a to M ?

@yashiel

This comment has been minimized.

yashiel commented Feb 8, 2016

yes which one is best to use..

@cesc1989

This comment has been minimized.

cesc1989 commented Feb 26, 2016

@tripciergedev @yashilanka I don't think there's a better approach. The important thing here is to distinguish how to properly declared functions when thinking about ordering code in a file.

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.

One should keep a style (from the ones that work) along a project always in favor os JS hoisting.

Just my two cents.

@diego-vieira

This comment has been minimized.

diego-vieira commented Mar 1, 2016

๐Ÿ‘ great

@kashishgupta1990

This comment has been minimized.

kashishgupta1990 commented Apr 8, 2016

great!

@termitek12

This comment has been minimized.

termitek12 commented Apr 17, 2016

Excellent!

@grantstrotter

This comment has been minimized.

grantstrotter commented May 2, 2016

Very helpful explanation. Thank you!

@zero5100

This comment has been minimized.

zero5100 commented May 5, 2016

Very nice, thanks!

@jdjuan

This comment has been minimized.

jdjuan commented May 16, 2016

Excellent explanation, thanks for taking the time on creating this resource ๐Ÿ˜ƒ

@ghost

This comment has been minimized.

ghost commented May 17, 2016

Thanks for this!

@fdrobidoux

This comment has been minimized.

fdrobidoux commented May 21, 2016

Very helpful, thanks m8!

@RoyalRajdeep

This comment has been minimized.

RoyalRajdeep commented May 31, 2016

๐Ÿ‘

@Shujito

This comment has been minimized.

Shujito commented Jun 6, 2016

I use A

@madhums

This comment has been minimized.

madhums commented Jun 9, 2016

I use B

@AdeshM

This comment has been minimized.

AdeshM commented Jun 22, 2016

Great! ๐Ÿ‘

@dinusuresh

This comment has been minimized.

dinusuresh commented Jul 7, 2016

๐Ÿ‘

@mike123henry

This comment has been minimized.

mike123henry commented Aug 14, 2016

This is very helpful!!!
I recently ran into this pattern and wish I had found your explanation before I had to debug it.

var x = "hi";

(function sayHi(passed) {
console.log(passed)
})(x);
//works

@miguelm3

This comment has been minimized.

miguelm3 commented Aug 19, 2016

Thanks! Very helpful for starters like me!

@sunnykgupta

This comment has been minimized.

sunnykgupta commented Aug 29, 2016

For those still wondering which of the following is better, my suggestion is you read up further on the language. These demonstrations help us understand how the language works. Which way to use depends upon what you are trying to achieve and how you plan to format your code.

To learn more about the JS language, try to read SpeakingJS.

@dpaksoni

This comment has been minimized.

dpaksoni commented Oct 5, 2016

Great

@MikePap

This comment has been minimized.

MikePap commented Nov 30, 2016

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

@neocxf

This comment has been minimized.

neocxf commented Dec 22, 2016

Thanks for your sharing. Help me clarify a lot

@RecDev

This comment has been minimized.

RecDev commented Jan 22, 2017

Great! Thanks for sharing.

@nturbanov

This comment has been minimized.

nturbanov commented Jan 24, 2017

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

@machsx

This comment has been minimized.

machsx commented Mar 16, 2017

Nice to have all such examples gathered here. Thanks!

@Rrrapture

This comment has been minimized.

Rrrapture commented Apr 4, 2017

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

@englishextra

This comment has been minimized.

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

This comment has been minimized.

aloerina01 commented Apr 27, 2017

๐Ÿ‘

@alexnlfm

This comment has been minimized.

alexnlfm commented May 16, 2017

Very useful tutorial! Thanks a lot!

@zimejin

This comment has been minimized.

zimejin commented May 22, 2017

JavaScript is so wild.

@levarne

This comment has been minimized.

levarne commented Jul 25, 2017

๐Ÿ‘ leka man

@DanChab

This comment has been minimized.

DanChab commented Aug 6, 2017

awesome...

@HimmelsturmerIX

This comment has been minimized.

HimmelsturmerIX commented Sep 7, 2017

why e.js does not work?

@Ghanshyam-K-Dobariya

This comment has been minimized.

Ghanshyam-K-Dobariya commented Jan 5, 2018

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

@tienthanhjlw

This comment has been minimized.

tienthanhjlw commented Jan 25, 2018

Thanks :)

@pgimeno

This comment has been minimized.

pgimeno 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

This comment has been minimized.

mohamedhafezqo commented May 28, 2018

๐Ÿ‘

@Clburguete

This comment has been minimized.

Clburguete commented Jun 7, 2018

Great. Thanks!

@RajkamalSR

This comment has been minimized.

RajkamalSR commented Nov 16, 2018

Great examples. Thanks ;)

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