I’ve been reading Kyle Simpson’s “Scope and Closures” from the “You Don’t Know JS” series for our new DD book club.
Chapter 1 deals with defining scope, and understanding the relationship between the scope, engine and compiler. The code is compiled before it is executed.
The scope is a set of rules for looking up variables.
The compiler declares a variable in the current scope.
The engine looks up the variable and assigns it a value.
An LHS (left hand side) lookup is for the purpose of assigning to the variable. It looks up the container, not the value.
An RHS (right hand side) lookup’s purpose is to retrieve the value of the variable.
eg. in the following assignment operation
x = 4
x is the target of the assignment and 4 is the source, or value of the assignment.
In the above example, foo is an RHS lookup. a is an LHS lookup, because it is being implicitly assigned the value 2, by the 2 being passed as an argument to the function foo.
The compiler will look for a variable in the current scope, and if it cannot find it, it will go up a level and continue to do so until it finds a matching var declaration.
If it does not find a match, for an LHS lookup it will be automatically defined in the global scope (unless using ‘strict mode’). If it does not find one for an RHS lookup, it will throw a reference error.
A reference error is when the variable cannot be found.
A type error is when the var can be found in an RHS lookup, but the action is illegal or impossible.
An identifier is the name of a variable already declared.
Global variables can be referenced from the global object eg.
Lexical scope is only defined where the function is declared.
eval() can cheat scope by dynamically generating code. This is not worth the performance hit.