- Tokenizing/Lexing: breaking up a string of characters into tokens.
- Parsing: taking a stream (array) of tokens and turning it into a tree of nested elements (Abstract Syntax Tree).
- Code-Generation: the process of taking an AST and turning it into executable code.
- Engine: responsible for start-to-finish compilation and execution of our JavaScript program.
- Compiler: handles all the work of parsing and code-generation.
- Scope: collects and maintains a look-up list of all the declared identifiers (variables), and enforces a strict set of rules as to how these are accessible to currently executing code.
How to cheat Lexical scope? There are two ways: eval(..) and with, but it's a very bad idea, because of it defeats the Engine's ability to perform compile-time optimizations
- Functions
- let/const from ES6 with blocks ({})
- try/catch structure
- All declarations are moved to their respective scopes
! Function declarations are hoisted before normal variables
Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.
Wrong code:
for (var i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
Right code:
for (var i=1; i<=5; i++) {
(function(j){
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})( i );
}
Or
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}