JavaScript has a very sophisticated compiler that checks hundreds of lines of code in milliseconds to see if it contains any errors. If there is an error, not one line of code will be executed. If there are no errors, the code will be executed. When a variable is assigned, e.g. a = 5, a left hand side (LHS) lookup is performed to find the variable in memory so it can assign the number 5 to it. Scope lookup stops once it finds the first match. When JavaScript is not in strict mode and reaches the global environment, it will assign the value to a global variable.

See the Pen thecodelog.com - JS Scope 1 by Deano (@deangilewicz) on CodePen.

When JavaScript is in strict mode and reaches the global environment, it will throw a ReferenceError.

See the Pen thecodelog.com - JS Scope 2 by Deano (@deangilewicz) on CodePen.

When a right hand side (RHS) lookup is performed, e.g. a;, and is not found anywhere in scope a ReferenceError will be thrown.

See the Pen thecodelog.com - JS Scope 3 by Deano (@deangilewicz) on CodePen.

Lexical scope is the context in which values and expressions can be referenced. It is based on where variables and blocks of scope are authored and is defined by author-time decisions when functions are declared. Lexical scoping looks in the current scope then goes up one level. Scope allows access to same level scope variables and functions:

See the Pen thecodelog.com - JS Scope 4 by Deano (@deangilewicz) on CodePen.

Scope allows access to higher level (outer) scope variables and functions:

See the Pen thecodelog.com - JS Scope 5 by Deano (@deangilewicz) on CodePen.

Scope does not allow access to lower level (inner) scope variables and functions:

See the Pen thecodelog.com - JS Scope 6 by Deano (@deangilewicz) on CodePen.

Variables defined inside a function cannot be accessed from outside the function.

See the Pen thecodelog.com - JS Scope 7 by Deano (@deangilewicz) on CodePen.

When using nested functions, the nested (inner) function is private to its containing (outer) function. Below, the inner function (square) forms a closure and this function can use the arguments and variables of the outer function (addSquares), while the outer function cannot use the arguments and variables of the inner function.

See the Pen thecodelog.com - JS Scope 8 by Deano (@deangilewicz) on CodePen.

The same identifier name can be specified at multiple layers of nested scope, which is called shadowing:

See the Pen thecodelog.com - JS Scope 9 by Deano (@deangilewicz) on CodePen.

There are two ways in JavaScript that can “cheat” lexical scope: 1. eval(..) 2. with The eval function modifies existing lexical scope by evaluating a string of code which has one or more declarations in it. It takes a string as an argument, and treats the contents of the string as if it had actually been authored code at that point in the program.

See the Pen thecodelog.com - JS Scope 10 by Deano (@deangilewicz) on CodePen.

When strict mode is used, eval function operates in its own lexical scope, which means declarations made inside of the eval function do not actually modify the enclosing scope.

See the Pen thecodelog.com - JS Scope 11 by Deano (@deangilewicz) on CodePen.

With creates a separate lexical scope by treating an object reference as a scope and that objects properties as scoped identifiers (properties become registered variables in that scope). If With is used then the JavaScript compiler will not do code optimizations and it will not work in strict mode.

See the Pen thecodelog.com - JS Scope 12 by Deano (@deangilewicz) on CodePen.

In addition to being a bad idea to use, both the eval function and with keyword are restricted by strict mode. With is outright disallowed, whereas various forms of indirect or unsafe eval functions are disallowed while retaining the core functionality. They also both defeat the javaScript engine’s ability to perform compile-time optimizations which results in slower code.