What is scope?
A scope defines the visibility or accessibility of a variable. In vernacular, whether a variable can be accessed or referenced is determined by its scope.
There are three scopes in JavaScript.
- global scope
- Function scope (local scope)
- Block scope
let globalVariable = "I am a variable under global scope" function func() { let localVariable = "I am a variable under local scope" } if (true) { let blockVariable = "I am a variable under block scope" }
Global Scope
A variable defined in the outermost layer is in the global scope, and the variables in the global scope can be accessed anywhere in the program.
var globalVariable = "Global scope variable" function func() { // Accessing globally scoped variables within a function console.log("Intra function access:", globalVariable) } func() console.log("Out of function access:", globalVariable)
Output:
Intra function access: global scope variables Out of function access: global scope variables
Variables defined with var keyword in braces (including pure braces, if, while, and for) still belong to the global scope.
if (true) { var globalVariable = "Global scope variable" } console.log("External access:", globalVariable)
Output:
External access: global scope variables
Function Scope (Local Scope)
The variables defined in the function belong to the function scope, also known as local scope. Variables within a local scope can only be accessed within their own scope.
function func(params) { var localVariable = "Local scope variable" console.log("Intra function access:", localVariable) } func() console.log("External access:", localVariable) // Uncaught ReferenceError: localVariable is not defined
Output:
Intra function access: locally scoped variables Uncaught ReferenceError: localVariable is not defined
In the example, we tried to access a variable defined in the local scope externally, and reported an error that the variable is undefined.
Block Scope
Let and const are introduced in ES6, which is different from var. In the previous example, the variables defined with VaR between braces (including pure braces, if, while, and for) are in the global scope. If we define it in braces with let and const, the variable will be in the block scope.
Variables within the scope of a block can only be accessed within its own scope.
let differs from const in that const defines a constant and cannot modify the defined value.
{ let blockVariable = "Block scope variable" console.log("Intra block access:", blockVariable) } console.log("External access:", blockVariable) // Uncaught ReferenceError: blockVariable is not defined
Output:
Intra block access: block scoped variables Uncaught ReferenceError: blockVariable is not defined
In the example, we tried to access a variable defined in the scope of the block externally, and reported an error that the variable is undefined.
What is a scope chain? Scope Chain
When a variable cannot be found in the current scope, it will try to find its outer scope. If it cannot be found, it will continue to look outside (it will only look outside, not brother scope, let alone inside). This search rule like a chain is called a scope chain.
let variable1 = "I'm variable 1, external" let variable2 = "I'm variable 2" function func() { let variable1 = "I'm variable 1, internal" { let variable3 = "I'm variable 3" } { // Look outside and find it in the upper function console.log(variable1) // Look outside until the global scope console.log(variable2) // If it is not found, an error is reported console.log(variable3) // Uncaught ReferenceError: variable3 is not defined } } func()
Output:
I'm variable 1, internal I'm variable 2 Uncaught ReferenceError: variable3 is not defined
In the example, when printing the variable1 variable, the search is stopped because the variable1 variable is found in the upper scope, that is, the function, and the variable1 variable under the global scope will not be found.
When looking for the variable2 variable, if it is not found in the upper scope, the upper scope, that is, the variable2 variable under the global scope, is always found.
When looking for the variable3 variable, because the variable3 variable is defined in the sibling scope, it will not be found, because the rule of the scope chain is to only look for the upper scope, not the sibling scope. Therefore, an error of undefined variable is reported here.
The scope of a function is the scope when it is defined, not when it is called
function func() { let variable = "I am func Variables within" function func2() { console.log(variable) } return func2 } { let variable = "I'm a variable in braces" let func2 = func() func2() }
Output:
I am func Variables within
In the example, when executing func2 function, the scope looking up is the scope when func2 is defined, not the scope when func2 is called.
What happens if the variable cannot be found?
If a variable cannot be found until the global scope, the following operations will be performed.
- Non strict mode: implicit declaration of global variables
- Strict mode: error reporting
Non strict mode
In non strict mode, when trying to assign a variable, if it is not found, it will be implicitly declared as a fully local variable.
{ variable = "I am an implicitly declared variable" } console.log(variable)
Output:
I am an implicitly declared variable
In the above example, because variable is not declared, it is implicitly declared as a variable under the global scope, which enables the value of variable variable to be printed on the outside.
In non strict mode, when trying to use the value of a variable, an error will also be reported if it is not found.
{ console.log(variable) // Uncaught ReferenceError: variable is not defined }
Output:
Uncaught ReferenceError: variable is not defined
In the above example, an undefined error is reported because variable is not defined when it is used.
Strict mode
Adding "use strict" indicates that it is a strict mode. In the strict mode, errors will be reported regardless of assignment or the use of undeclared variables.
"use strict" { variable = "I am an implicitly declared variable" // Uncaught ReferenceError: variable is not defined }
Output:
Uncaught ReferenceError: variable is not defined
Scope benefits?
- Prevent naming conflicts: you write 10000 lines of code files. If there is no scope, you have to give each variable a unique name. It's torture to think about it.
- Security: the variable will not be accessed externally, which ensures that the variable value will not be modified at will. If the variable you define in the function can be accidentally modified after thousands of lines, your toes will know it is torture.
- More advanced syntax: the implementation of encapsulation and object-oriented is inseparable from the isolation of variables, which depends on the scope.
Say something reasonable.
When writing code, there is no need to distinguish the concepts of global usage domain, local scope and block scope. Just remember that braces are a scope, and looking for variables is always from the inside out. Now our editors basically have indentation formatting, from the position of the current code block layer by layer to the left, which is all the variables it can reference.
For example, every family is a scope. When we need a surgical fee and can't afford it, we must find it at home first, ask our parents, brothers and sisters, and won't turn to other strange families for help. If you haven't, go outside to the scope of acquaintance relationship. If you can't, ask the neighborhood committee for help. The neighborhood committee can no longer ask the state for help. Starting from the closest relationship, the circle goes out layer by layer, which is the scope and scope chain.
Finally, we strongly recommend that you use let to name variables and give up var!