Scope defines the current context of execution. Based on this context of execution, scope will determine what variables, functions, objects are accessible during runtime.
But what is the context of execution or the execution context? It is the environment in which the current code is being evaluated in.
In this post, we will uncover the different types of scope: global, local or function and block. We should also understand what lexical scope and the scope chain is.
When we start defining non-nested functions and variables in a JavaScript document, we are in the global scope. There is only one global scope in a JavaScript document. Any variable that is defined outside of any function or object is in the global scope and therefore available inside of all functions and objects.
In the above example, the variable friend and getFriend function are defined in the global scope. The variable enemy and internal function getEnemy are not in global scope but in function scope or a local scope.
Anytime we define a function with two set of brackets we create a function scope. Any variables or functional definitions inside of this function are in that local scope or that functions scope. And each time we call this function, there will be a different function scope for every call of this function.
Because no non-nested functions can access variables from other functions, we can have the same variable names in different functions. This is because those variables are bound to the execution context of that function. Each will have different scopes, and will not accessible in other functions. Global scope will also not have access to these function scopes.
But what about if statements, and other loops? They create a block scope.
Anytime we define an if statement, switch statement, while loop, for loop, etc. within two set of brackets, we create a block scope. But what about variables we define within the block scope. Can we access them outside of this block scope?
One of the key differences between var, let and const is that var is function scoped, while let and const are block scoped. (Explained here)
As you can see from the example, we can only access friend outside of the block scope created by the if statement.
But if this if statement was inside of a function, we would not be able to do access any of the variables.
Lexical scope is scope that is defined at the time when compiler processes your code. Lexical scope will be based on where variables and blocks of scope are defined by the author during runtime and how the JavaScript engine will find them when executing your code.
Lexical scope is what allows the children scope have access to the variables defined in the parent scope. The children functions are therefore lexically bound to the execution context of their parents.
Each execution context that is created has a link outside of its own lexical environment called the scope chain. The scope chain gives us access to variables in the parent environment.
The JavaScript engine will look in the inner most function for any declarations before going outwards to the global environment.
In the above example, each function can only go outside of its own functional scope to see if the parent scope has the needed variables. You cannot however access a child functions variables in the parents functional scope.
Below are some more examples to solidify your knowledge of scope.