In each programming language, its variables have a certain valid range. After exceeding this range, the variables will become invalid. This is the scope of the variable. From a mathematical point of view, it is the domain of independent variables.
Scope is the accessible range of variables, that is, scope controls the visibility and life cycle of variables and functions. In JavaScript, objects and functions are also variables, and variables are defined inside the arbitrary function body nested by the declaring their function body and the arbitrary function body nested.
1. Static scope and dynamic scope
Static scope
It means that the scope of the declaration is determined at compile time based on the program body, also known as the lexical scope. Most modern programming languages adopt static scope rules, and JavaScript adopts this scope.
In languages that use static scopes, the innermost nested scope rules are basically: the identifier introduced by a declaration is visible in the scope where the declaration is located, and also in each scope nested inside, unless it is covered by another declaration of the same name identifier nested inside.
In order to find the object referenced by a given identifier, it should be found in the current innermost scope. If a declaration is found, the object referenced by the identifier can be found. Otherwise, we will search in the direct outer scope and continue to check the outer scope in order to the outside until we reach the outermost nesting level of the program, that is, the scope where the global object declaration is located. If no declaration is found at all levels, then the program has an error. as follows:
function cha(){ var name = "xiao;" function chb() { function chc() { console.log(name); } } }First, the function searches for the definition of name from chb(), and then continues to search up layer by layer. Finally, the definition of name is found in cha(). If it is not found, an error will be reported.
2. Dynamic scope
In a dynamically scoped language, the object referenced by a variable in the program is determined based on the program's control flow information at the moment of the program's running.
2. The scope of JavaScript
There are two scopes in JavaScript, namely the global scope and the local scope.
1. Global Scope
There is a definition anywhere in the code. Even if a global variable is defined in a piece of js code nested in the html page, the variable can still be accessed in the referenced js file. This is very likely to cause pollution to global variables.
The variables in the following three cases will be considered global variables
(1) The outermost function and the outermost variable have a global scope
(2) Variables that are directly assigned without definition are automatically declared to have global scope
(3) The properties of all window objects have global scope
2. Local Scope
Local scopes can generally be accessed only in fixed code snippets, such as variables inside functions (function scope)
var name = "xuxiaoping";function echoName() { var firstname = "xu";//local scope secondname = "xiao";//global scope function echoFirstName() { console.log(first name);//xu } console.log(secondname); return echoFirstName;}console.log(name);//global scope var f = echoName();f();console.log(firstname);console.log(secondname);The result is:
xuxiaoping
xiao
xu//Inner function can access variables of outer function
undenfined //The internal variables of the function cannot be accessed outside the function
xiao
JavaScript attaches global variables to window objects and becomes a property of window objects.
3. Function scope
Block-level scope: Any set of statements in braces belongs to a block, and all variables defined in this are invisible outside the code block. Most C-class languages have block-level scopes.
However, an important feature of JavaScript is that it has no block-level scope.
function echoi() { for(var i = 0;i<10;i++){ ;//console.log(i); } if(true){ var str = "hello"; } console.log(i); console.log(str);}echoi();The output result is:
10
hello
It can be seen that outside the for statement (or if, while), the variable i defined in the block is still accessible. That is, JavaScript does not support block-level scopes, it only supports function scopes, and variables defined anywhere in a function are visible anywhere in that function. As someone who learns C and java from the beginning, this is a bit difficult to adapt. According to my tests, the same is true for PHP.
Of course, you can use the closure characteristics of JavaScript to simulate block-level scope
function echoi() { (function() { for(var i = 0;i<10;i++){ ;//console.log(i); } })(); if(true){ var str = "hello"; } console.log(i); console.log(str);}echoi();The result is: i undefined
This isolates the definition of variables. In js, in order to prevent naming conflicts, global variables and global functions should be avoided as much as possible, so this kind of closure is used in many ways.
4. JavaScript variable life cycle
The JavaScript variable lifecycle is initialized when it is declared.
Local variables are destroyed after the function is executed.
Global variables are destroyed after the page is closed.
3. JavaScript scope chain
It looks like a chain, it can probably be combined with the linked list in the data structure.
In JavaScript, functions are objects, but in fact, everything in JavaScript is objects. Function objects, like other objects, have properties that can be accessed through code and a series of internal properties that are only accessible to the JavaScript engine. One of the internal properties is [[Scope]], defined by the third edition of the ECMA-262 standard. This internal properties contain a collection of objects in the scope created by the function. This collection is called the scope chain of functions, which determines which data can be accessed by functions.
When a function is created, its scope chain is populated with data objects that are accessible in the scope of the function. For example, define a function like this:
function add(num1,num2) { var sum = num1 + num2; return sum;}When the function add is created, a global object will be filled in its scope chain, which contains all global variables, as shown in the figure below (note: the picture only gives some of all variables):
The scope of function add will be used during execution. For example, execute the following code:
var total = add(5,10);
When executing this function, an internal object called "execution context" is created. The runtime context defines the environment at which the function is executed. Each runtime context has its own scope chain for identifier parsing. When the runtime context is created, its scope chain is initialized as an object contained in [[Scope]] of the current running function.
These values are copied into the scope chain of runtime context in the order in which they appear in the function. Together they form a new object called "activation object", which contains all local variables, named parameters, parameter sets and this function. Then this object will be pushed into the front end of the scope chain. When the running context is destroyed, the active object will be destroyed. The new scope chain is shown in the figure below:
During function execution, every time a variable is encountered, an identifier parsing process will be passed to decide where to get and store data. This process starts from the head of the scope chain, that is, searches for an identifier of the same name from the active object. If it is found, use the variable corresponding to this identifier. If it is not found, continue to search for the next object in the scope chain. If all objects are not found after searching, the identifier is considered undefined. During the execution of the function, each identifier must go through such a search process.
4. Scope chain and code optimization
From the structure of the scope chain, it can be seen that in the scope chain of the runtime context, the deeper the identifier is, the slower the read and write speed will be. As shown in the figure above, because global variables always exist at the end of the context scope chain during runtime, it is the slowest to find global variables when parsing the identifier. Therefore, when writing code, you should try to use global variables as little as possible and use local variables as much as possible. A good rule of thumb is: if a cross-scope object is referenced more than once, store it in a local variable before use. For example, the following code:
function changeColor(){document.getElementById("btnChange").onclick=function(){ document.getElementById("targetCanvas").style.backgroundColor="red"; };}This function refers to the global variable document twice. The variable must be searched through the entire scope chain until it is finally found in the global object. This code can be rewritten as follows:
function changeColor(){ var doc=document; doc.getElementById("btnChange").onclick=function(){ doc.getElementById("targetCanvas").style.backgroundColor="red"; };}This code is relatively simple and will not show a huge performance improvement after rewriting, but if a large number of global variables in the program are accessed repeatedly, the performance of the code after rewriting will be significantly improved.
5. With change scope chain
The corresponding runtime context is unique every time the number is executed, so calling the same function multiple times will lead to the creation of multiple runtime contexts. When the function is executed, the execution context will be destroyed. Each runtime context is associated with a scope chain. Generally speaking, during the running context, its scope chain will only be affected by the with statement and the catch statement.
The with statement is a quick way to apply objects to avoid writing duplicate code. For example:
function initUI(){ with(document){ var bd=body, links=getElementsByTagName("a"), i=0, len=links.length; while(i < len){ update(links[i++]); } getElementById("btnInit").onclick=function(){ doSomething(); }; }}Use width statements here to avoid writing the document multiple times, which looks more efficient, but actually creates performance problems.
When the code runs to the with statement, the scope chain of the runtime context is temporarily changed. A new mutable object is created, which contains all the properties of the object specified by the parameter. This object will be pushed into the head of the scope chain, which means that all local variables of the function are now in the second scope chain object, so access is more expensive. As shown in the figure below:
Therefore, with statements should be avoided in programs. In this example, simply storing the document in a local variable can improve performance.
Summarize
1. The scope of a variable is where the scope of the variable is valid.
2. The scope chain of variables is the collection of objects in the scope that are created.
The above is all about this article, I hope it will be helpful for everyone to learn JavaScript programming.