(1) Scope
The scope of a variable is the area of this variable defined in the program source code.
1. Lexical scope is used in JS
Variables not declared in any function (the omitted var in the function is also considered global) are called global scopes.
Variables declared within a function have a function scope and are local variables
Local variables have higher priority than global variables
var name="one"; function test(){ var name="two"; (name); //two } test();
The omission of var in the function will affect the global variable because it has actually been rewritten as a global variable.
var name="one"; function test(){ name="two"; } test(); (name); //two
Function scope, that is, the function is the basic unit of a scope, and js does not have block-level scope like c/c++, such as if for, etc.
function test(){ for(var i=0;i<10;i++){ if(i==5){ var name = "one"; } } (name); //one } test(); //Because it is a function-level scope,So you can access itname="one"
Of course, higher-order functions are also used in js, which can actually be understood as nested functions
function test1(){ var name = "one"; return function (){ (name); } } test1()();
After test1(), the outer function will be called, and an inner function will be returned. Then () will be continued, and the inner function will be executed accordingly, so the output "one" will be output.
Nested functions involve closures, and we will talk about them later. Here, the inner function can access the variable name declared in the outer function, which involves the scope chain mechanism.
2. Declaration in JS is ahead of schedule
Function scope in js means that all variables declared within a function are always visible within the function body. Moreover, variables can be used before declaration, which is called hoisting
tip: Declaration is done when the js engine is precompiled. Before the code is executed, the phenomenon of declaring advance occurs.
for example
var name="one"; function test(){ (name); //undefined var name="two"; (name); //two } test();
The above achieves the following effect
var name="one"; function test(){ var name; (name); //undefined name="two"; (name); //two } test();
Try to remove the var? This is the name in the function has become a global variable, so it is no longer undefined
var name="one"; function test(){ (name); //one name="two"; (name); //two } test();
3. It is worth noting that none of the above mentioned parameters are passed. If the test has parameters, what if?
function test(name){ (name); //one name="two"; (name); //two } var name = "one"; test(name); (name); // one
As mentioned before, the basic type is passed by value, so the name passed into the test is actually just a copy, and the copy is cleared after the function returns.
Don't think that the name="two" in the function has changed the global name, because they are two independent names
(2) Scope chain
The above-mentioned advanced functions involve scope chains
function test1(){ var name = "one"; return function (){ (name); } } test1()();
1. Introduce a large passage to explain:
Each piece of js code (global code or function) has a scope chain associated with it.
This scope chain is an object list or linked list. This set of objects defines the "scope" variables in this code.
When js needs to find the value of the variable x (this process is called variable resolution), it will start from the first object of the chain. If this object has a property named x, the value of this property will be directly used. If there is no property named x in the first object, js will continue to look for the next object on the chain. If the second object still does not have a property named x, it will continue to look for the next one, and so on. If no object on the scope chain contains the attribute x, then it is considered that x does not exist on the scope chain of this code, and a reference error (ReferenceError) exception is finally thrown.
2. Examples of scope chains:
In the top-level code of js (that is, the code within any function definitions) the scope chain consists of a global object.
In the function body that does not contain nesting, there are two objects on the scope chain. The first is an object that defines function parameters and local variables, and the second is a global object.
In a nested function body, there are at least three objects on the scope.
3. Scope chain creation rules:
When defining a function (note that it starts when it is defined), it actually saves a scope chain.
When this function is called, it creates a new object to store its parameters or local variables, and adds the object to that scope chain, while creating a new longer "chain" representing the scope of the function call.
For nested functions, the situation changes again: each time the external function is called, the internal function will be redefined again. Because every time an external function is called, the scope chain is different. Internal functions have subtle differences every time they are defined - every time they call external functions, the code of the internal functions is the same, and the scope chain associated with this code is also different.
(tip: Understand the above three points well and remember them. It is best to be able to say them in your own words, otherwise memorize them, because the interviewer will ask you directly: Please describe the scope chain...)
Here is a practical example of scope chains:
var name="one"; function test(){ var name="two"; function test1(){ var name="three"; (name); //three } function test2(){ (name); // two } test1(); test2(); } test();
The above is a nested function, and the corresponding one should be that there are three objects on the scope chain.
Then when calling, you need to find the value of name, and look up on the scope chain.
When the test1() is successfully called, the order is test1()->test()->global object window. Since the value of name three is found on test1(), the search is completed and returned.
When the test1() is successfully called, the order is test2()->test()->global object window. Since the value of name is not found on test2(), I look for the name in test(), find the value of name two, and complete the search and return.
There is another example that sometimes we make mistakes and are often deceived during interviews.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:///TR/xhtml1/DTD/"> <html xmlns="http:///1999/xhtml"> <head> <script type="text/javascript"> function buttonInit(){ for(var i=1;i<4;i++){ var b=("button"+i); ("click",function(){ alert("Button"+i); //It's all Button4 },false); } } =buttonInit; </script> </head> <body> <button >Button1</button> <button >Button2</button> <button >Button3</button> </body> </html>
Why?
According to the search rules for variables in the scope chain:
("click",function(){ alert("Button"+i); },false);
There is a function here, which is an anonymous function. Since it is a function, it has an object on the scope chain. The variable i is used in this function, and it will naturally look for it in the scope.
The search order is this anonymous function -->External function buttonInit() -->Global object window
I cannot be found in the anonymous function, so I naturally ran to buttonInit(), ok, found in for.
At this time, the registration event has ended. Don't think it will put i down one by one, because the variables within the function scope are always visible in the scope, that is, they will remain until the last state
When the anonymous function wants to use i, the registration event is finished, and i has become 4, so it is all Button4
So how to solve it?
Pass the value to it. Each time you loop, use an anonymous function to pass the i in the for. The rules of the anonymous function are like code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:///TR/xhtml1/DTD/"> <html xmlns="http:///1999/xhtml"> <head> <script type="text/javascript"> function buttonInit(){ for(var i=1;i<4;i++){ (function(data_i){ var b=("button"+data_i); ("click",function(){ alert("Button"+data_i); },false); })(i); } } =buttonInit; </script> </head> <body> <button >Button1</button> <button >Button2</button> <button >Button3</button> </body> </html>
This will do Button1..2..3
4. The above is the basic description of the scope chain. In addition, the with statement can be used to temporarily expand the scope chain (with is not recommended)
The syntax is as follows:
with(object)
statement
This with statement adds object to the head of the scope chain, then executes statement, and finally restores the scope chain to its original state
Simple usage:
For example, assign value to the value of each item in the form
Generally we can do this directly
var f = [0]; = ""; = ""; = "";
After introducing with (because using with will cause a series of problems, so use the above form)
with([0]){ = ""; = ""; = ""; }
In addition, if an object o has an x attribute, = 1;
Then use
with(o){ x = 2; }
It can be converted to = 2;
If o does not define the attribute x, its function is just equivalent to x = 2; a global variable.
Because with provides a shortcut to read the properties of o, it cannot create properties that o itself does not have.
To understand the scope scope of a variable, you must first understand the scope chain
When declaring a variable with the var keyword, it is to add a property to the object where the variable is located.
Scope chain: Since js variables are attributes of objects, and this object may be attributes of other objects, and all objects are attributes of window objects, the relationship between these objects can be regarded as a chain
The head of the chain is the object where the variable is located, and the tail of the chain is the window object.
Look at the following code:
function t() {
var a;
function t2() {
var b;
}
}
Functions in js are also objects, so the object where the variable a is located is t, and t is in the window object, so the scope chain of a is as follows
t--window
So the object in b is t2, t2 is included in t, and t is in the window object, so the scope chain of b is as follows
t2--t--window
After understanding the scope chain, we will start the scope analysis of the variables.
1 JavaScript Variables without var are global variables and are properties of window objects
function test1() {
//When executing this sentence, it will look for the scope object. This function is the first object in the scope chain, but there is no relevant var statement in this object.
//Yu Li looks for the second object in the scope chain, that is, the global object, and there are no relevant var statements in the global object.
// Since there is no relevant var statement, js implicitly declares the variable, i.e. var all, in a function;
all = 30;
alert(all);
}
test1();
alert(all);
alert();
2 Variables defined within a function (except functions within a function) are valid within the entire function.
function test2() {
var t = 0;
//Define variables in the for conditions, the scope chain object of this change is this function
//So it is valid in the whole function
for (var i = 0; i < 5; i++) {
t += i;
}
alert(i);
}
test2();
3 Variables inside the function replace global variables with the same name
var t = "bb";
function test() {
//When executing t, it will first look for the scope chain object. Since it is defined inside the function, this function is the first object of its scope chain.
//There is also a definition of t in this object, so t is a local variable, which replaces the global variable t
//t is just defined at this time, but there is no assignment, and the assignment is on the next line, so undefined is output here
alert(t);
var t = "aa";
alert(t);
}
test();
4 No block scope
if (true) {
//A variable is defined in the block, and the first object of its scope chain is the global object window
var tmp = 0;
}
//The first object in the scope chain of tmp is the global object window, and there are related var statements in the global object, so the output is 0
alert(tmp);
The following content comes from the summary of reading online blogs. When using notes, only the key points are recorded. At the same time, I am very grateful to the bloggers who are willing to share. It is you who let me stand by the shoulders of the giant!
1、
var temp = (function(){
var name ="test";
return function(){
alert(name);
}
})();
The above code snippet is a writing method that we often see in jser, and it is a legendary closure. As we all know, calling temp(); will pop up "test"; this process can be explained by the following three theories:
1) The js scope is only related to the function's delimiter, and the function and the nesting of functions form a scope chain;
2) The rule of creating scope chains is to copy the scope chain of the previous layer of environment and place a pointer to the object of this environment variable at the beginning of the chain;
3) In Javascript, if an object is no longer referenced, then the object will be recycled by GC. If two objects are referenced to each other and are no longer referenced by the third person, then the two objects referenced to each other will be recycled.
If you don't understand after reading the above 3 items, you can see the detailed explanation of the code based on the theory:
First, the outer function is executed and destroyed; but the scope chain of the outer function is copied into the scope chain of the inner function, forming part of the scope chain of the inner function. Remember to be copied, not a reference (according to Article 2), so the inner function can still access name; since the returned inner function is referenced by temp, after the outer function is executed and destroyed, although the inner function is part of the outer function, it still exists, just as the third basis, it is referenced by a third party; the legendary closure is the principle