Let’s start with function
bad() that tries to
access not defined variable:
As we would expected attempt to read
ends with an error, namely
Now you may be wondering what will happen when we try to write value to not defined variable:
In this case we get no error and everything seems to work,
but after a call to
notDefinedVariable is still visible.
What happened here is that we accidentally create
notDefinedVariable global variable.
Using global variables is regarded by many programmers as
bad practice, especially when you can create them accidentally.
To prevent errors and encourage good programming style
introduced so called strict mode.
We can enable strict mode by beginning function with
With strict mode enabled we get
when we try to write to undefined variable:
You may be wondering what will happen when we declare variable but didn’t assign any value to it, will we get an error while accessing variable value or not?
We didn’t get an error, that’s because variables declared using
initially have value of
undefined until explicitly assigned by the user.
Now let’s look on a bit more complicated example:
You may wonder what happened here. We already know that reading
from undefined variables causes
ReferenceError exception, but
why first call to
console.log(x) didn’t throw any?
And what about
undefined value that was printed,
we know that this is the value of declared but not initialized variables.
So to sum up this function behaves as if variable
x was declared
at the very beginning of
matter where you declare variables inside function body
because they declarations will be implicitly
moved to the beginning of the function.
behaves exactly the same as
As you may expect hoisting can make troubles when we are not alert, for example can you spot a bug here:
i was accessible only inside
for(var i ...) loop
interpreter would spot problem with
and would thrown a
ReferenceError exception. Unfortunately
because of hoisting
i is accessible through entire function body and only
wrong behaviour of our program can tell us that something is wrong.
So how can we make our programs secure against bugs caused by hoisting? The simples thing to do is to declare all function variables at the beginning of function body, thus making hoisting explicit:
This is simple and effective solution but a bit cumbersome to use,
it would be better to declare variables in the place of their first usage
right? So the second solution is to just ignore the problem, if
you are keeping size of your function small (no longer than 20 lines
of code) and you follow good coding practices (especially you give
your variables good descriptive names, and prefer
forEach method to
you should have no problems with hoisting.
In some cases you really want to reduce visibility of a variable to some block of code, the popular solution to this problem is to use IIFE pattern:
i is visible only inside IIFE expression.
Using IIFE has it’s own problems especially when we want to
this value inside IIFE expression.
We must either pass
this via local variable:
call() to invoke function:
Almost every popular language (e.g. Java, C#, C++) follows block scoping rules, this means that variable is visible only inside a block of code in which it is declared. For example in Java:
If you have this strange feeling that something is wrong here
you are not the only one.
var but with lexical scoping.
Here’s how our example looks with
let also prohibits redeclarations of variables:
I hope you now know what hoisting is and what troubles it can make. If you have any remarks how I can improve this article please leave a comment.