Most of the contact js are the first to be used to learn, in fact, most of the most of learning a language should be taken in this way. Because just go to practice, but also started, but if look at it, it is easy to estimate not go to school. So yeah, in order to deceive others, first of all have to deceive themselves (pretend to be, and then started working, will not go to school, then go to fool other people, but if they feel cheated, then honestly look at the video and books, doing notes, again and again, then you really can fool someone else). ^ 0 ^
First of all, read the book helped me understand the two most important knowledge js - The closure also this point, the next point is the compiler theory and object prototype.
Here the record about knowledge closures. Understand the need to first understand before closure js compiler theory, inquiry and variable scope.
1. Basics
1.1 compiler theory
Although JavaScript is usually classified as a "dynamic" or "interpreted" language, but in fact it is a compiled language. It is not compiled in advance, compared to the compiler of the traditional compiled languages, JavaScript engine is much more complex.
For JavaScript, the compiler most cases occur within a few microseconds of time before the code is executed. Any JavaScript code snippet must be compiled before execution, and then executed.
On var a = 2;
the compilation process:
Encountered var a, check the variable name exists in the same scope, presence is ignored, or else declare a new variable a;
Generating runtime code required for processing the
a = 2
assignment;
When the code is executed, the engine will look for variable a, if found, will be assigned, otherwise it will throw an exception.
Find about 1.2 variables
Inquiry into variables LHS查询
and RHS查询
, above assignment will be LHS查询
.
When inquiries were RHS LHS variable appears conducted inquiries at the left side of an assignment operation, it appears on the right.
Target assignment is who
LHS
and who is the source of an assignmentRHS
.
LHS查询
It is trying to find the variables of the container itself, which can assign it a value. RHS查询
Find the equivalent value of a variable, RHS查询
not "the right side of an assignment" in the true sense, more precisely "non-left side."
Such as console.log( a );
, which is a reference to a RHS references, and a = 2;
references to a LHS is a reference, because in fact we do not care what the current value is yes.
expand
function foo(a) {
var b = a;
return a + b;
}
var c = foo( 2 );
Here LHS查询
there is at 3, RHS查询
there are four, one also needs to call a method foo RHS查询
, the need to pass parameters 2
assigned to the formal parameters method a
.
About 1.3 Scope
作用域
Find the variable name is based on a set of rules. Usually it requires taking into account several作用域
.
When a function block or nested within another block or function, occurs 作用域的嵌套
. When the current scope of a variable can not be found, the engine will (one level) in the outer nested 作用域
continue to look until you find the variable, or reach the outermost 作用域
(that is 全局作用域
) so far.
If the RHS查询
variable you want is not found, the engine will throw ReferenceError
an exception.
When the engine executes LHS查询
, if can not find the target variable in the global scope, global scope will create a variable with that name, and return it to the engine, provided that in the non "strict mode."
If RHS查询
successful, but the variables are unreasonable operation, it will throw TypeError
an exception.
Shadowing effect
Scope search stops at the first match of the identifier.
Global variables will automatically become a global object (such as window object browser) properties, which can be accessed through the global object variable: window.a
; but in any case unable to access global variables are non-shielded.
Deceive lexical
function foo(str, a) {
eval( str ); // 欺骗! console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3
Use eval
in the method foo declare variables b
and assignment, masking global variables b
.
In the program's strict mode, eval (..) has its own lexical scope at runtime, which means that the statement can not modify the scope is located.
with usage
var obj = { a: 1, b: 2 };
foo(obj){
with (obj) {
a = 3;
b = 4;
c = 5;
}
}
foo(obj)
console.log(obj.a) // 3
console.log(obj.c) // undefine
console.log(c) // 5
1.4 Scope function
It refers to a scope function, using all the variables belonging to this function may be in the range of the entire function (including nested scopes) and multiplexing.
The minimum authorized or minimal exposure guidelines: in software design, should be minimally exposed to the necessary content, and other content will be "hidden", such as API design a module or object.
Scope of benefits:
Avoid conflicts
Global namespace variable conflicts with third-party libraries easily occur.
Using the scope rules force all identifiers can not be injected into the shared scope, but remains in private, no conflict of scope, which can effectively circumvented all accidental clashes.
var a = 2;
(function foo(){ // <-- 添加这一行
var a = 3;
console.log( a ); // 3
})(); // <-- 以及这一行
console.log( a ); // 2
Function will be treated as a function of expression rather than a standard function declaration to deal with.
Function declarations and expressions easiest way to distinguish is to look at the position of the function keyword appears in the declaration (not just one line of code, but the entire statement of position). If the function is declared in the first word, then that is a function declaration, otherwise, it is a function expression.
The most important difference between function statements and function expressions is their name identifier will be bound where.
Anonymous function expression
setTimeout( function() {
console.log("I waited 1 second!");
}, 1000 );
Function expression can not name identifier, and the function declaration is not a function name can be omitted.
Anonymous function expression has about several drawbacks:
Anonymous function in the stack trace does not show a meaningful function names, making it difficult to debug.
When the function only need to refer to their use have expired arguments.callee references, such as recursion. And the event listener requires unbundling itself after the event trigger.
Affect code readability.
Recommended to be named, writing:
setTimeout( function timeoutHandler() {
console.log( "I waited 1 second!" );
}, 1000 );
Immediate execution function expression (IIFE)
var a = 2;
(function foo(a) {
a += 3;
console.log( a ); // 5
})(a);
console.log( a ); // 2
advantage:
- The external object as a parameter, and variable named anything you feel appropriate name. Help improve code style.
- Resolve undefined identifier defaults are covered by an exception error caused.
undefined = true; // 给其他代码挖了一个大坑!绝对不要这样做!
(function IIFE( undefined ) {
var a;
if (a === undefined) {
console.log( "Undefined is safe here!" );
}
})();
- Inverted code run sequence, a function to run a second.
var a = 2;
(function IIFE( def ) {
def( window );
})(function def( global ) {
var a = 3;
console.log( a ); // 3 console.log( global.a ); // 2
});
1.5 Scope
Superficially JavaScript is not related to the function block scope.
for (var i=0; i<10; i++) {
console.log( i );
}
Here i
it will be bound outside the scope (global or function) in a.
Block scope of use : from local variable declaration should be used as close as possible, and to maximize localization.
Block scope is a tool for the principle of least privilege to be extended before the hidden information in the block code from the hidden information in the function extension
When var
you declare a variable, write it where are all the same, because they will eventually belong to the external scope.
Examples scope block:
with
Structure is the key block of scope.try/catch
Thecatch
clause would create a block scope, where variables declared only in thecatch
internal valid.let
Keywords can be bound to any variable scope is located. Variable block its statement implicitly where the scope.const
Keywords can also be used to create a variable block scope, but its value is fixed (constant).
var foo = true;
if (foo) {
var a = 2;
const b = 3; // 包含在 if 中的块作用域常量
a = 3; // 正常!
b = 4; // 错误!
}
console.log( a ); // 3
console.log( b ); // ReferenceError
let
Key role:
-
let
The statement will not be carried out to enhance the block scope. Declared before the code is executed, the statement does not "exist." - And closures and garbage collection mechanism to reclaim memory related.
function process(data) {
// 在这里做点有趣的事情
}
// 在这个块中定义的内容可以销毁了!
{
let someReallyBigData = { .. };
process( someReallyBigData );
}
-
for循环
Let's head not onlyi
bound to thefor
block of the cycle, in fact it will be re-bound to each iteration of the loop to ensure that when the value of the use of a loop iteration end of the re-assignment.
for (let i=0; i<10; i++) {
console.log( i );
}
console.log( i ); // ReferenceError
1.6 upgrade
Example 1.6.1:
a = 2;
var a;
console.log( a ); // 2
Example 1.6.2:
console.log( a ); // undefine
var a = 2;
When you see that
var a = 2;
, you may think this is a statement. But in fact it will be seen as two declarations:var a;
anda = 2;
. The first definition statement is made at compile time. The second assignment statement would be left in place waiting for the implementation phase.
This process is like variable and function declarations from the position in which they appear in the code is "moved" to the top. This process is called lift.
Function declarations and variable declarations will be improved. But the details is worth noting that a function will be lifted first, and then the variable.
Example 1.6.3:
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
Example 1.6.4:
foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}
Example 1.6.5:
foo(); // "b"
var a = true; if (a) {
function foo() {
console.log("a"); }
}
else {
function foo() {
console.log("b");
}
}
Despite repeated var statement it will be ignored, but the function declarations that appear in the back or front cover can.
2. Closure
Closures in JavaScript is everywhere, you just need to be able to recognize and embrace it.
Closures are based on the natural result of lexical scope when writing the code generated, and you do not even need to use them consciously to create closure.
When the function can remember where and when access lexical scope, it creates a closure, even if the function is executed outside of the current lexical scope.
function foo() {
var a = 2;
function bar() {
console.log( a ); // 2
}
bar();
}
foo();
bar()
Of the a
method reference is to find lexical scoping rules, and these rules are only part of the closure. However, according to the previous definition, this is not a closure.
The following piece of code, a clear demonstration of closure:
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 这就是闭包的效果。
Function bar()
lexical scope can access the foo()
internal scope. Then we will bar()
function itself as a value type is passed.
Understanding closures
In foo()
the execution, usually we expect foo()
the entire scope inside were destroyed. Indeed inner scope persists (due bar()
itself to use), and therefore are not recycled.
Thanks to the bar()
position declared by the gift, it has to cover foo()
inside the scope of the closure, so that the scope has been able to survive for bar()
at any time after reference.
bar()
Still holds a reference to the scope of, and this is called a reference to closure.
function wait(message) {
setTimeout( function timer() {
console.log( message );
}, 1000 );
}
wait( "Hello, closure!" );
timer
It has covered wait(..)
the scope of the closure, and therefore also retain variable message
references.
wait(..)
After the implementation of 1000 ms, it will not disappear internal scope, timer
function still retain wait(..)
scope of the closure.
Cycle and closures
Example 2.1:
for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i ); // 6 6 6 6 6
}, i*1000 );
}
Example 2.2:
for (var i=1; i<=5; i++) {
(function() {
var j = i;
setTimeout( function timer() {
console.log( j ); // 1 2 3 4 5 6
}, j*1000 );
})();
}
Example 2.3:
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout( function timer() {
console.log( j ); // 1 2 3 4 5
}, j*1000 );
})( i );
}
Example 2.1: based on the scope of works, although the circulation of five functions are defined separately in each iteration, but they are enclosed in a shared global scope, so in fact there is only one i
. Since the function of the delay execution, executing the loop until the final call, to give i
a value of 6.
Example 2.2: anonymous functions has its own scope variables j
to store in each iteration i
values.
Example 2.3: 2.2 Example code modifications.
Use within iterations IIFE
will have generated for each iteration a new scope, so that the callback function of delay new scope can be enclosed within each iteration, each iteration will contain a variable with the correct value for our visit .
2.1 module
function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
This mode is referred to in JavaScript module. We keep internal data variables are hidden and private status. This can be seen as an object type of the return value of the module is essentially a public API.
Mode two necessary conditions modules:
There must be an external closed function, which must be called at least once.
Blocking function must return the at least one internal function, so that the internal function can be formed in the closures private scope, and may be private access or modify state.
Objects without a closure function from the function call returned, only the data attribute is not a real module.
Singleton
var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
Loader / manager
var MyModules = (function Manager() {
var modules = {};
function define(name, deps, impl) {
for (var i=0; i<deps.length; i++) {
deps[i] = modules[deps[i]];
}
modules[name] = impl.apply( impl, deps );
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
};
})();
The core code is modules[name] = impl.apply(impl, deps)
. To define the function module introduces package (any dependency can be passed), and the return value, which is the API module, a module is stored under the name in the list to manage.
Using the Module:
MyModules.define( "bar", [], function() {
function hello(who) {
return "Let me introduce: " + who;
}
return {
hello: hello
};
});
var bar = MyModules.get( "bar" );
console.log(
bar.hello( "hippo" )
); // Let me introduce: hippo
to sum up
The time and learning, not a pleasure. Read again books, then take notes, and review it again, do not understand some of this knowledge to understand, and also found some pass undetected knowledge.
Long ago, the next class of so and so each examination paper must be repeated cook 6 times, each time the results are then arranged in the forefront. His mother was my teacher, though not learned from this approach to learning where the teacher, but the teacher but I feel that learning is a happy thing, I am very glad met such a teacher.
Reproduced in: https: //www.jianshu.com/p/5ae0cc6bdbb4