--- title: Scope & Closures description: JavaScript, Scope, Closures image: tags: js lintConfig: MD004: style: "consistent" MD006: false published: false --- # Lexical Scope Lexical scope is controlled entirely by the placement of functions, blocks, and variable declarations, in relation to one another. JS is typically classified as an interpreted scripting language. Actually, JS is parsed/compiled in a separate phase before right before execution begins. Scope is primarily determined during compilation. Proof of this are syntax errors, early errors, and hoisting. Compilation creates a map of all the lexical scopes that lays out what the program will need while it executes. While scopes are identified during compilation, they’re not actually created until runtime, each time a scope needs to run. In the next chapter, we’ll sketch out the conceptual foundations for lexical scope. ## Syntax errors An exception caused by syntactically invalid code. Syntax errors are detected while compiling or parsing source code. ```javascript= console.log('SyntaxError test') const foo = .'5'; // SyntaxError: expected expression, got '.' function bar() {}} // SyntaxError: expected expression, got '}' ``` If JS was executing top-down line by line (i.e. interpreted), the `console.log()` statement should be printed before the `SyntaxError` is thrown. ## Early Errors ```javascript= console.log("Howdy"); saySomething("Hello","Hi"); // SyntaxError: Duplicate parameter name not allowed in this contsxt function saySomething(greeting,greeting) { "use strict"; console.log(greeting); } ``` ## Hoisting ```javascript= function foo() { var color = "red"; { color = "green"; // ReferenceError: Cannot access 'bar' before initialization let color = "blue"; console.log(color); } } ``` --- The code author’s decisions on where to place variables, functions, and blocks with respect to each other are analyzed according to the rules of scope, during the initial parsing/compilation phase. The resulting scope structure is generally unaffected by runtime conditions. JS functions are themselves first-class values; they can be assigned and passed around just like numbers or strings. But since these functions hold and access variables, they maintain their original scope no matter where in the program the functions are eventually executed. This is called closure. One important application of closure is the module pattern. Modules are a code organization pattern characterized by public methods that have privileged access (via closure) to hidden variables and functions in the internal scope of the module. You should always declare the variable by name before you use it. But you only need to declare a variable once for each scope, it can be used as many times after that as needed. In JavaScript, each function gets its own scope. Scope is basically a collection of variables as well as the rules for how those variables are accessed by name. Only code inside that function can access that function’s scoped variables. * A variable name has to be unique within the same scope. * The same variable name a could appear in different scopes. * A scope can be nested inside another scope * If one scope is nested inside another, code inside the innermost scope can access variables from either scope. * Code in one scope can access variables of either that scope or any scope outside of it # Function Scope You use the `var` keyword to declare a variable that will belong to the current function scope, or the global scope if at the top level outside of any function. ## Hoisting Wherever a var appears inside a scope, that declaration is taken to belong to the entire scope and accessible everywhere throughout. Metaphorically, this behavior is called hoisting, when a var declaration is conceptually "moved" to the top of its enclosing scope. Technically, this process is more accurately explained by how code is compiled, but we can skip over those details for now. >It’s not common or a good idea to rely on variable hoisting to use a variable earlier in its scope than its var declaration appears; it can be quite confusing. It’s much more common and accepted to use hoisted function declarations. ## Nested scopes When you declare a variable, it is available anywhere in that scope, as well as any lower/inner scopes. If you try to access a variable’s value in a scope where it’s not available, you’ll get a `ReferenceError` thrown. If you try to set a variable that hasn’t been declared, you’ll either end up creating a variable in the top-level global scope (bad!) or getting an error, depending on "strict mode". In addition to creating declarations for variables at the function level, ES6 lets you declare variables to belong to individual blocks (pairs of { .. }), using the let keyword. Besides some nuanced. Block scoping is very useful for managing your variable scopes in a more fine-grained fashion, which can make your code much easier to maintain over time. # Immediately Invoked Function Expressions (IIFEs) # Closure Closure is one of the most important, and often least understood, concepts in JavaScript. You can think of closure as a way to "remember" and continue to access a function’s scope (its variables) even once the function has finished running. ## Modules The most common usage of closure in JavaScript is the module pattern. Modules let you define private implementation details (variables, functions) that are hidden from the outside world, as well as a public API that is accessible from the outside.