Hoisting, Shadowing, Closures
Notes about some mysterious sounding terms in Javascript.
Hoisting
This refers to how Javascript internally moves all declarations to the top of the current scope (imagine a crane hoisting = lifting them up to the top). That scope could be the whole script or the function they are in, blocks like if/for
don’t define their own scope.
So
is actually
but
is
this has unexpected consequences, for example:
here this will log 2
since it’s interpreted as:
There are some rules that makes this trickier. First, a function declaration (function foo(){...}
) takes priority over a variable declaration (var foo = 1
).
In this case:
this will log 1
. It is like if it was written like:
Here:
this will log 1
, since this is like if we had
so the line foo=2
is not changing the variable in the parent scope but its new independent foo
Other interesting thing is that with a function declaration everything get’s lifted to the top, the name and the body of the function, instead of just the name. This is for the function declarations (function foo() { ... }
), not the function expressions (var foo = function foo() { .... }
), that behave like the others.
Here i get lost with the terminology some times:
So
returns 1, but
fails
Shadowing
Imagine that you had a variable, and you wanted to use another with the same name inside a method, in that case you would shadow the outer variable like this:
This works with functions, not with within an if
for example. In coffeescript you have to be keep in mind that you might be altering another variable in the same script since you can’t shadow them using var
, but there are other options:
1) If you can use ECMAScript 6, you have the option to use a block scope with let
:
2) Use a Immediately-Invoked Function Expression (IIFE) = self-executing anonymous function (or self-invoked anonymous function)
(function() { ... })();
Closure
This is the fact that a function that is defined inside another, will keep access to all the variables of this parent function, even after this parent function exits.
Let’s say that you have something like
–
Related: This is bug that we had, in which were executing a series of functions with a setTimeout without realizing that the reference to the function was being replaced (instead of creating a closure to preserve them)
See the Pen javascript issue by Fernando Sainz (@fsainz) on CodePen.
Links:
- http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
- https://github.com/joeytwiddle/coffeescript-gotchas
- http://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/