Pit "The word, in this meaning is" trap ". Because JavaScript "weak language" nature, make it in the use of abnormal loose flexible, but also extremely easy "recruit". These pits are often hidden, so must be polished eyes, in order to learn and apply JS Road on the smooth sailing.
One, global variables
JavaScript manages scopes through functions. Variables declared inside a function are only within this function and are not available outside of the function. On the other hand, global variables are declared outside of any function or are not declared straightforward to use.
"Do not declare direct and simple use" means declaring a variable without the var keyword. This we have been very clear, the way to avoid the implicit generation of global variables is to declare variables as much as possible with the Var keyword.
But you think it's OK to use Var? Take a look at this pit:
Copy Code code as follows:
function foo () {
var a = b = 0;
Body ...
}
Maybe you expect two local variables, but B is a real global variable. Why? Because assignment is from right to left, so this is equivalent to:
Copy Code code as follows:
function foo () {
var a = (b = 0);
Body ...
}
So b is a global variable.
Landfills: variable statement, the best to come, do not engage in wholesale ~_~;
II. Declaration of variables
First look at the pit:
Copy Code code as follows:
myname = "global";
function foo () {
alert (myname);
var myname = "local";
alert (myname);
}
Foo ();
At first glance, we expect the results of two alert to be "global" and "local", but the real result is "undefined" and "local". Why? Because variables in the same scope (same function), declarations are raised to the top of the scope to parse first.
So the execution behavior of the above code fragment may be like this:
Copy Code code as follows:
function foo () {
var myname;
alert (myname); "Undefined"
myname = "local";
alert (myname); "Local"
}
Use another pit to test if you really understand the pre-resolution:
Copy Code code as follows:
if (! () A "in Window") {
var a = 1;
}
alert (a);
The declaration of a variable was advanced to the top of the code and was not assigned at this time. Next, enter the IF statement to determine the condition in which the "a" in window has been established (a has been declared as a global variable), so the judgment statement evaluates to false and jumps out of the IF statement directly, so A's value is undefined.
Copy Code code as follows:
var A; "Undefined"
Console.log ("A" in window); True
if (! () A "in Window") {
var a = 1; Do not perform
}
alert (a); "Undefined"
Landfills: variable declaration, preferably manually at the top of the scope, for variables that cannot be assigned at the moment, you can take a method of assigning values first.
Third, function declaration
Function declarations are also advanced to the top of the scope, before any expressions and statements are parsed and evaluated
Copy Code code as follows:
Alert (typeof foo); "Function"
function foo () {
Body ...
}
Can compare:
Copy Code code as follows:
Alert (typeof foo); "Undefined"
var foo = function () {
Body ...
};
Understand this truth of you, whether you will step on the following pits?
Copy Code code as follows:
function Test () {
Alert ("1");
}
Test ();
function Test () {
Alert ("2");
}
Test ();
Run the above code fragment, see two times window display is "2", Why not respectively "1" and "2"? Quite simply, the declaration of test is resolved before test (), because the latter overrides the former, so two execution results are "2".
Landfills: In most cases, I use a function expression instead of a function declaration, especially in some statement blocks.
Iv. Expression of functions
Let's take a look at a named function expression, for granted, it must have a name, for example:
Copy Code code as follows:
var bar = function Foo () {
Body ...
};
Note that the function name is only visible inside its function. such as the following pits:
Copy Code code as follows:
var bar = function Foo () {
Foo (); Normal operation
};
Foo (); Error: Referenceerror
Landfills: Do not use a named function expression (except for some recursion and debug purposes), and do not apply the function name to the external.
V. Self-execution of functions
For a function expression, it can be executed by following (), and the arguments can be passed in parentheses, and the function declaration is not possible. Keng:
Copy Code code as follows:
(1) This is just a grouping operator, not a function call!
So here the function is not executed, it's still a declaration.
function foo (x) {
alert (x);
} (1);
The following code fragment performs the pop-up display "1", because before (1), it is a function expression, so the () non-grouping operator, instead of the operator, represents the invocation execution.
Copy Code code as follows:
Standard anonymous function expression
var bar = function foo (x) {
alert (x);
} (1);
Previous () Converts a function declaration to an expression
(function foo (x) {
alert (x);
}) (1);
The whole () is an expression
(function foo (x) {
alert (x);
} (1));
New expression
New function foo (x) {
alert (x);
} (1);
&&, | |,!, +,-, etc. operators (and commas), eliminating ambiguity in function expressions and function declarations
So once the parser knows that one of them is already an expression, the other defaults to the expression.
True && function foo (x) {
alert (x);
} (1);
Landfills: The key to this pit is to figure out the essence of the expressions of various functions.
Vi. closures in cycles
The following demo is a common pit:
Copy Code code as follows:
<!doctype html>
<meta charset= "UTF-8" >
<title>Document</title>
<body>
<ul>
<li><a href= "#" >link #0 </a></li>
<li><a href= "#" >link #1 </a></li>
<li><a href= "#" >link #2 </a></li>
<li><a href= "#" >link #3 </a></li>
<li><a href= "#" >link #4 </a></li>
</ul>
</body>
Copy Code code as follows:
var links = document.getelementsbytagname ("ul") [0].getelementsbytagname ("a");
for (var i = 0, L = links.length i < l; i++) {
Links[i].onclick = function (e) {
E.preventdefault ();
Alert ("You click link #" + i);
}
}
We expect that when I click on the link, we get the value of the sequence index I, which can be actually clicked on which link to get the end result of I after the loop: "5".
Explain why: When alert is invoked, the anonymous function expression inside the for loop retains the reference to the external variable I (the closure), at which point the loop ends and the value of I is modified to "5".
Landfills: To get the desired result, you need to create a copy of the variable i in each loop. The following demonstrates the correct approach:
Copy Code code as follows:
<meta charset= "UTF-8" >
<title>Document</title>
<body>
<ul>
<li><a href= "#" >link #0 </a></li>
<li><a href= "#" >link #1 </a></li>
<li><a href= "#" >link #2 </a></li>
<li><a href= "#" >link #3 </a></li>
<li><a href= "#" >link #4 </a></li>
</ul>
</body>
Copy Code code as follows:
var links = document.getelementsbytagname ("ul") [0].getelementsbytagname ("a");
for (var i = 0, L = links.length i < l; i++) {
Links[i].onclick = (function (index) {
return function (e) {
E.preventdefault ();
Alert ("You click link #" + index);
}
}) (i);
}
As you can see, (function () {...}) () in the form of the function mentioned above, I pass it as a parameter to Index,alert, and it has a reference to index, which is not changed by the loop. Of course, when you understand its rationale, you can also write this:
Copy Code code as follows:
for (var i = 0, L = links.length i < l; i++) {
(function (index) {
Links[i].onclick = function (e) {
E.preventdefault ();
Alert ("You click link #" + index);
}
}) (i);
}
It works too.