"You do not know js (on volume)," Notes 1 (basic knowledge and closures)

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:

  1. Encountered var a, check the variable name exists in the same scope, presence is ignored, or else declare a new variable a;

  2. Generating runtime code required for processing the a = 2assignment;

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 LHSand who is the source of an assignment RHS.

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 2assigned 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 ReferenceErroran 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 TypeErroran 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 evalin the method foo declare variables band 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:

  1. Anonymous function in the stack trace does not show a meaningful function names, making it difficult to debug.

  2. 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.

  3. 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 iit 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 varyou declare a variable, write it where are all the same, because they will eventually belong to the external scope.

Examples scope block:

  • withStructure is the key block of scope.

  • try/catchThe catchclause would create a block scope, where variables declared only in the catchinternal valid.

  • letKeywords can be bound to any variable scope is located. Variable block its statement implicitly where the scope.

  • constKeywords 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

letKey role:

  • letThe 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 only ibound to the forblock 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;and a = 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 amethod 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!" );

timerIt has covered wait(..)the scope of the closure, and therefore also retain variable messagereferences.

wait(..)After the implementation of 1000 ms, it will not disappear internal scope, timerfunction 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 ia value of 6.

Example 2.2: anonymous functions has its own scope variables jto store in each iteration ivalues.

Example 2.3: 2.2 Example code modifications.

Use within iterations IIFEwill 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

Guess you like

Origin blog.csdn.net/weixin_34247032/article/details/91266789