Javascript’s lexical scope, hoisting and closures without mystery.

Scope meets compiler

So, I mentioned that javascript is a compiled language, but what does this mean? Shortly, just before execution, the source code is sent by the engine trough a compiler, in which, during an early phase called lexing (or tokenizing), scope get defined. This doesn’t just tell us what’s in a name, but also remember us that lexical scope is based on where variables and blocks of scope have been authored in the source code. In other words, lexical scope is defined by you during author time and frozen by the lexer during compilation. Let’s show this with the help of a little example:

var a = ‘something’;

Engine meets scope

When engine executes the code that the compiler produced it will see our above example’s code to be something like:

a = ‘something’;
  1. If you are running in ES5 strict mode: engine would throw a ReferenceError as you would logically imagine,
  2. otherwise global scope will just create a variable with that name in the global scope and hand it back to the engine. We can imagine global scope’s reply to sounds like:

Function and Block level scope

What create a scope then? Although not completely true the common wisdom is that javascript has function-based scope only. Meaning that each declared function create its own scope. Let’s take the following example:

var a = 1; 
function foo() {
var a = 10;
console.log(a);
}
console.log(a); // 1
foo(); // 10
{
let foo = 10;
console.log( foo ); // 10
}
console.log( foo ); // ReferenceError
for (let i = 0; i < 5; i++) {
console.log( i ); // 0 1 2 3 4
}
console.log( i ); // ReferenceError

Hoisting

First, let see hoisting in action

foo(); // ‘hello hoisting’function foo() {
console.log(‘hello hoisting’);
}
foo(); // 3var foo;function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}
{
console.log( foo ); // ReferenceError!
let foo = 10;
}

Closures

In his book Kyle gives a very straightforward definition for what a closure is:

function foo() {  // 'scope of foo' aka lexical scope for bar
var memory = 'hello closure';
return function bar() {
console.log(memory);
}
}
var memory = null,
baz = foo();
baz(); // 'hello closure'

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store