Read "You don't know JavaScript" a book to make a note;
Compiler principle:
JS is a compiled language, similar to the traditional compilation language, the traditional compilation process is divided into three stages;
1. Word segmentation/lexical analysis; 2. Analytic/grammatical analysis; 3. Code generation;
JS engine in the compilation will be more complex concrete how complex I do not build, probably is the 1, 3 has been optimized for its rapid compilation and immediate execution, here to pay attention,, JS is compiled before the implementation of maybe a few microseconds ok
1. Scope://collect and maintain all declared variables to form a query mechanism, with a set of strict rules to ensure that the currently executing code access to these variables;
There are two working models of scopes, one is the universal use of static scopes, also called lexical scopes, and the other is dynamic scopes
with var a = 1; As an example
The compiler (1 2 3 above) is working, and when you see Var A, the compiler goes to ask the scope if there is a variable called a in the current scope's collection, if any, ignore continue compiling, if not, declare a variable in the current scope's collection, and generate the code for the engine to ship Line it, when the engine runs a = 1, the engine also asks the scope whether there is a variable called a in the current scope's collection, if the engine is used and it is assigned a value of 1, if it doesn't work, then ask the outer scope of the current scope to look up until the global scope (if the global scope also does not have scope to say " Your little ancestor didn't find it, but helped you create a "non-strict mode";
The engine has two ways of LHS and RHS when asking for variables in the scope. The one above is LHS; simply over lhs the object of the assignment operation RHS is the source of the assignment operation; Simply say var a = 1; Here A is LHS; Console.log (a) this is a RHS; in other words, an assignment is a value (well, so simple to understand);
The engine throws an Referenceerror exception when the RHS lookup fails in a non-strict mode (found to the global scope);
LHS Lookup fails (find global scope also not found) global scope will be very enthusiastic to create one for you;
The engine throws a similar referenceerror exception when LHS lookup fails in strict mode (found to global scope);
RHS lookup failure is the same as non-strict mode;
RHS If the variable is found, but when an unreasonable operation is made (such as when a numeric variable is used in a method) or when a null/undefined type is referenced, the engine throws TypeError;
Referenceerror is thrown when the scope lookup fails;
TypeError is scoped to find the successful, but did an unreasonable operation thrown;
1.0 scope Chain//When one function nests another function, it forms the scope of nesting creates the scope chain
var b = 1; function fn (a) { return a + b; } FN (2); // 3
When B makes a RHS query, it is not found in the scope collection of FN to look up the scope chain up here is the global scope
1.1. Lexical scope//is the first stage of the compilation principle the scope of the definition lexical is the scope of writing code is also called the static scope
function fn (a) { var b = a.num*2; function fn1 (c) { console.log (c); } FN1 (b+1); } FN ({"name": 2}); // 5
In this example, there are three levels of scope, which is 1. Global scope an identifier FN;2.FN scope three identifiers A, B, fn1;3.fn1 scope an identifier C;
Scopes find an identifier that stops when the first matching identifier is encountered, and a multi-tiered nested scope defines an identifier of the same name as a "masking effect" (an internal identifier obscures an external identifier); The
global variable becomes the property of the Global Object window, which allows access to the masked global identifier, but there is no way to access the identifier other than the global identifier if it is obscured;
No matter how the function is called and how his lexical scope is called, it is determined only by the location where the function is declared;
Lexical scopes find only one level identifier such as a, FN, arr; For object access such as Json.name.value, the lexical scope will only look for the JSON to find the identifier after the object property access rule takes over access to name and value respectively;
1.2 Spoofing the lexical scope//lexical scope is determined by writing code when the code is run to modify (spoof) lexical scope of means/way to achieve the purpose of the spoofing lexical scope
with eval (); For example:
eval () in js, accept a string as a parameter, code can be generated as if the program was written in the same way, and according to this principle eval () can achieve the purpose of the deceptive lexical scope;
var a = 2; function fn (str) { eval (str); // Deception Console.log (a); } FN (// 1
Here Str is written dead if necessary can be fully generated by the program itself;
in strict mode eval (); Having its own lexical scope does not affect the scope of the domain;
similar to eval (), and SetInterval (), the first parameter of SetTimeout () can be a string, the string is interpreted as a dynamic function code, and the new function ();
Here also prompts you not to use them, here is attached to a native package of a wheel compatible with IE7 string to JSON parsing function : https://github.com/liuyushao147/ Javascript_mincode
with (); and so it is not elaborated here;
Both know that Eval () with () Function () is the devil, which is too extreme if it is defined as the devil only because they deceive the lexical scope; JS engine will perform various optimizations during the compilation phase. One of them is to perform static analysis based on the morphology of the code, pre-determine their location so that they can be found quickly at runtime, but when the engine is found to have eval () with () and so on, it cannot determine what code they will accept, what modifications to the scope, so the engine ignores them without any optimizations. Too many function programs such as eval () in your code will run quite slowly, even though the engine is smart; sometimes it's even more magical to change global variables not just by using them incorrectly.
1.3 Function scope// means that all variables/identifiers of this function can be used and reused within its internal scope (nested scopes can also be used);
function fn () { var a = 1; function fn1 () { // code .... } };
The above code is the same as the three-level scope global FN and fn1, within the FN function can be accessed using variable a (FN1 can also be used), but under the global scope is not access to this a, it is FN private; Then we write a code like this:
var b; function Getadd (a) { = A+add (a+2); Console.log (b) } function Add (a) { return a*2 } Getadd (2); // Ten
A bit familiar, this may be a primer or beginner's general writing, so to speak true, the pre-problem is not big, but later maintenance costs are high, in the version of the iteration when the possible identifier coverage, why say, variable B and function add should be the Getadd function of the private property should be implemented within its If they are accessible externally, they are not only not necessary but may also produce more than getadd conditions; it is dangerous; so should privatize it.
function Getadd (a) { var b; function Add (a) { return a*2 } = A+add (a+2); Console.log (b); } Getadd (2); // Ten
So much more comfortable, B and add can not be accessed from the outside to be controlled only by the Getadd, and has no effect on the function, and also reflects the privatization of the design, more in line with the minimum authorization or minimum exposure principle; Look at the code:
function fn () { function fn1 (a) { = 2; Console.log (A*i); } for (var i=0;i<5;i++) { fn1 (--i); } } fn (); // Perfect for the browser to collapse ... i=2 accidental overwrite for i the loop condition is always met.
I know it's not going to be written in the real world. This code is mainly to clarify a concept hidden scope is the hidden scope of variables and functions; Many benefits can avoid identifier collisions and can prevent similar problems (masking effect can be a perfect solution to this embarrassment); also mention a solution to the global naming conflict there is a professional name for the global namespace, which is to hide their own private variable functions to provide only a variable ( typically JSON objects); Adding a wrapper function outside of any code snippet can achieve the purpose of hiding the scope, and the external function will not be able to access any content inside the wrapped function (not to mention closures), even if it is in the sky:
var a = 2; function // Add a wrapper function var a = 3; } fn (); Console.log (a); // 2
The same practice believes that even without this wrapper, no one would write it; on the other hand, the meaning of the packaging function is used; On the other hand, a pit is needed to jump down; The problem is that the function itself (FN) has contaminated its scope when adding a wrapper function. Think about n multi-wrapper function in a function The scene must be chaotic; okay, the function expression is on. The difference between a function declaration and an expression is a function if it is the first word of the declaration that is the declaration of functions or the expression.
An expression can be divided into an anonymous expression that executes an expression immediately (Iife), which is specifically recorded in the future; function expressions can solve this embarrassment.
Whistling, next to understand the concept of the next block scope JS is no block-level scope (ES3), with the keyword is a heterogeneous it like a block scope of the form can be self-aware of the goods, in addition to the with outer try Catch statement in the catch is also a block scope, ES6 With the concept of block scope and the use of the latter will be communicated;
What is the scope of the block for the egg? Let's just say that. It is an extension of the minimum authorization principle in a simple point if there is a block scope there is no need for the wrapper function. Look at the code:
for (Var i=0;i<5;i+=1) {...};
If JS has a block scope then the for I is only used in for, as expected I can also access to use for the outside,
JS has the concept of identifier promotion; I also do not repeat, but to the section code to feel
A = 1; var A; Console.log (a); // 1 Console.log (b); // undefined var b = 2;
3. Closures//When a function remembers and can access the lexical scope, a closure is generated even if the function is called outside the current scope;
function fn () { var a = 1; function fn1 () { console.log (a) } fn1 (); } fn (); // 1
This code is similar to the previous scope nested lookup rule fn1 scope can access an identifier under the FN scope A; Is this a closure? It looks like a closure, but strictly according to the above, he's not even though he can access the current lexical scope; continue
function fn () { var a = 1; function fn1 () { console.log (a) } return fn1; } var f = fn (); f (); // 1 Yes, here's a standard (easy to understand closure) closures
The lexical scope of FN1 () under analysis is able to access the internal scope of the FN, then we will fn1 () when a return value (fn1 as a type of a value is passed, the value type is the function type, in other words, as a function type of the value); then define F to accept the return value of FN (that is, fn1 () function), and then call itself f (), simply by referring to the FN intrinsic function fn1 by different variables;
When the FN is finished, the garbage collection mechanism of the engine usually reclaims the identifiers that are no longer in use, freeing up memory, and it looks as if FN can be recycled; in fact, the advantages of closures are reflected, and the internal scope of the FN is not recycled; How could this be, oh, the internal scope of the FN1 is still in use AH , Fn1 declares in the internal scope of the FN that it has permission to cover the internal FN scope, so that the FN scope persists so that the fn1 is referenced at any time; Yes, that reference is a closure;
About closures There are a variety of ways to do this, regardless of how the value of the function type is passed, a closure is generated when the function is called:
function fn () { var a =1; function fn1 () { console.log (a); } FN2 (FN1); } function fn2 (f) { F (); } fn (); // 1
Yes, the F () is a closure. Next, say Iife (execute function immediately);
function fn () { var a = 1; (function f () { conosle.log (a); } ()) } fn ();
This f function is not executed outside of its lexical scope, and according to this view Iife seems not to be closed Bao, iife that is, the function f above is not in the lexical scope of execution, but in the definition of the lexical scope of the execution of a is found by ordinary lexical scope lookup rules rather than closures, and in theory closures should occur at the time of definition, Iife does create closures, or the most common tool for creating closures, although it does not actually use closures;
functionA () {varb =NewArray (); for(vari = 0; I < 10; i++) {B[i]=function (){ returni; } } returnB}varc =A (); for(vari = 0,len = C.length; i < Len; i++) {Console.log (C[i] ())//10 x}
This is embarrassing, using iife to improve
functionA () {varb =NewArray (); for(vari = 0; I < 10; i++ ){ (function() {B[i]=function (){ returni; } })(); } returnB}varc =A (); for(vari = 0,len = C.length; i < Len; i++) {Console.log (C[i] ())//10 x}
This is even more embarrassing, and still no, what's going on iife not be able to create closures. Take a closer look at the original we created the Iife scope is empty Ah, nothing is simply saying we need to include something for iife in this is I;
functionA () {varb =NewArray (); for(vari = 0; I < 10; i++ ){ (function (){ varj =i; B[J]=function (){ returnJ; } })(); } returnB}varc =A (); for(vari = 0,len = C.length; i < Len; i++) {Console.log (C[i] ())//0-9}
The whistling. This is possible, in fact, any use of callbacks in the use of closures, closures are essentially a standard, is about how the function is passed by value in the lexical scope of the code written. No doubt the closure is powerful, can use him to achieve a variety of modules, such as closures are ubiquitous;
Finally welcome the great God to correct!
JavaScript from scope to closure-notes