Scope in JavaScript
What is Scope?
Scope is the area of code where a variable (or function) exists and is accessible. There are a few different types of scopes in JavaScript: Global Scope, Function Scope and Block Scope.
Global Scope
Variables declared outside of functions or blocks (curly braces { }) are considered to have global scope meaning that they can be accessed anywhere in the JavaScript program
NOTE: When defining variables using the var keyword outside of a function (hence globally scoping it), the variable becomes attached to the window object. Variables defined with let or const do not get attached to the window object. This is because var was designed to be either function or global scoped. let and const are actually created to be block scoped
The window object represents the browser’s window and contains all global functions, objects and variables.
So technically, when you declare a variable using let and const outside of a code block in a javascript program, they are only globally scoped to the javascript program, but they are not in the global scope of the window object.
Function Scope
A variable declared within a function is considered to be part of the function’s scope. This scope is referred to as function scope. You will sometimes see function scope also referred to as local scope.
Variables declared inside a function scope can be accessed from within the function but not outside of it.
NOTE: Variables declared with the var keyword have function (a.k.a. local) scope when defined inside a function. Variables declared with let and const technically have block scope (inside curly braces) when declared inside a function (i.e. the variable’s scope is bound to the curly braces, and not to the function itself). Since the function uses curly braces to encapsulate the function body, the function scope and the block scope for the function body are essentially the same thing.
The below example demonstrates the differences between function scoping when using var and let
Block Scope
Block scope was introduced in ES2016 along with the let and const variable declaration keywords. Block scope only applies to variables created with either the let or const keywords.
Block scope is the scope defined within a set of curly brackets { }. The curly brackets define a “block” of code, hence the name, “block scope”.
A block scoped variable cannot be accessed outside of the block that it was defined in.
NOTE: Variables declared with the var keyword do NOT have block scope, only variables declared with let or const have block scope. Variables declared with var will ignore block scoping rules.
See the example below of how variables declared with the var keyword do not follow block scoping:
Lexical Scope
JavaScript is a lexically scoped language (as opposed to a dynamically scoped language). You will also see Lexical Scoping defined as Static Scoping. So what does lexical scoping mean?
Lexical scoping means that the scope is defined at the location where the variable and function is defined (as opposed to where they are run).
See the example below of how Lexical Scoping works:
Let’s break down the code snippet above.
1. When the logVariable( ) function is called, it creates a local variable x and sets its value equal to 50.
2. In the next line, the myFunc( ) function is called, let’s go up to where the myFunc( ) function is defined.
3. myFunc( ) calls the console.log( ) function on the x variable however, x is not defined in the myFunc( ) scope. We therefore need to go up one scope to the global scope to get the value of x which is 1. (see section below on scope chaining).
Notice that we never accessed the value of x = 50, even though it appears right above the myFunc( ) call in the logVariable( ) function. Again, this is because lexical scoping requires us to go to where the functions are defined, and not where they are run. If JavaScript were a dynamically scoped language, calling logVariable( ) would result in the value of 50 being logged to the console instead of 1.
Scope Chaining
It is very helpful to understand how JavaScript accesses variables using scope chaining. Understanding the concept of scope chaining will help you understand how to determine the scope of variables / functions.
When a function or method needs to access a variable in JavaScript which is not initialized with a value in the current scope, JavaScript will go up by one scope level to look for the variable’s value. It will keep going up scope levels until it finds the function declaration.
NOTE: Notice that scope chaining does not go DOWN scope levels, it will always only go up to look for a variable declaration in the next larger scope
Example of how scope chaining works: