First, scope

1, phase cheat morphology

There are two mechanisms in JavaScript that can “cheat” lexical scopes: eval(..) And with. The former allows you to evaluate a string of “code” containing one or more declarations to modify existing lexical scopes (at run time). The latter essentially creates a new lexical scope (again at run time) by treating a reference to an object as a scope and an object’s attributes as identifiers in the use domain.

1.1 the eval ()

function foo(str, a) {
    eval( str ); / / cheating! console.log( a, b ); } var b = 2; foo("var b = 3;", 1); / / 1 and 3Copy the code

In strict mode programs, eval(..) At runtime it has its own lexical scope, meaning that declarations in it cannot change the scope they are in.

 function foo(str) {
    "use strict";        
     eval( str );         
     console.log( a ); // ReferenceError: a is not defined     
 } 
 foo( "var a = 2"); Note: / /"use strict"The purpose of the code is to specify that the code executes under strict conditions. // In strict mode you cannot use undeclared variables. // Strict mode is added in the header of a script or function"use strict";
Copy the code

The eval ()

The eval function is used to parse json objects; Its function is to parse the corresponding string into JS code and run it.

Grammar:

eval("("+jsonObj+")")
Copy the code

Here’s an example.

function name1(){
   console.log('name1')}function name2(){
   console.log('name2')
 }
 var m="name1";
 eval(m+'()'); / / run name1 (); m='name2';
eval(m+'()'); / / run name2 ();Copy the code

1.2 with ()

Another feature in JavaScript that is difficult to master (and still not recommended) for cheating lexical scopes is the with keyword. With is often used as a shortcut to refer repeatedly to multiple properties in the same object without having to refer repeatedly to the object itself.

var obj = { a: 1, b: 2, c: 3 }; // A monotonous repetition"obj"obj.a = 2; obj.b = 3; obj.c = 4; // Simple shortcut with (obj) {a = 3; b = 4; c = 5; }Copy the code

With the usage ()

The with statement is used to set the scope of code in a particular object. In other words, with encapsulates an object and reduces the number of calls to an object.

Grammar:

var str="hello"; with(str){ alert(toUpperCase()); / / output"HELLO"
}
Copy the code

Let’s do another example, and think about the result.

functionfoo(obj) { with (obj) { a = 2; } } var o1 = { a: 3 }; var o2 = { b: 3 }; foo( o1 ); console.log( o1.a ); // 2 foo( o2 ); console.log( o2.a ); // undefined console.log( a ); // 2 -- No, a is leaked to the global scope!Copy the code

Do you have any questions so far??


To review the above problem, assignment a = 2 actually creates a global variable a. What’s going on here? In simple terms, with can treat an object with no or multiple attributes as a fully isolated lexical scope, so the attributes of the object are also treated as lexical identifiers defined within that scope. eval(..) Whereas a function that accepts code with one or more declarations changes its lexical scope, the with declaration essentially creates an entirely new lexical scope out of thin air based on the object you pass to it. Ok, here we understand hey hey!

Block scope

Var and let have a lot of scope in es6. Let and var have lots of scope in es6. The following will be interesting ^_^

2.1 the let and var

ES6 introduces the new let keyword, which provides an alternative way to declare variables in addition to var. The let keyword binds variables to any scope they are in (usually {.. } inside). Code analysis:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function() { console.log(i); }; } a[6](); / / 10Copy the code

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function() { console.log(i); }; } a[6](); / / 6Copy the code

The difference between the two codes is the scope used by var and let. 1. The scope of var variable is global, while let is local block scope, i.e. inside the for loop. 2. Make it clear that the I inside the loop is in a different scope than the I in console.log(I); they have separate scopes. 3. Global variable uniqueness. The variable I declared by var is overridden in the loop and ends up being a unique 10, so no matter which array of A is called in the external call, it ends up being 10. 4. Local use of the LET definition is only valid within the scope of the function. Give a chestnut a fine grind:

for (let i = 0; i < 10; i++) {
  // ...
}
console.log(i);
// ReferenceError: i is not defined
Copy the code

2.2 const

In addition to let and var, ES6 introduces const, which can also be used to create block-scoped variables, but whose value is fixed (constant). In other words: const declares a read-only constant. Once declared, the value of a constant cannot be changed. A variable declared by const may not change its value, which means that a const, once declared, must be initialized immediately and cannot be left for later assignment. Code analysis:

var foo = true; 
if(foo) { var a = 2; const b = 3; / / included inifBlock scope constant a = 3; / / normal! b = 4; / / error! } console.log( a ); // 3 console.log( b ); // ReferenceError!Copy the code

const foo;
// SyntaxError: Missing initializer inConst declaration the above code indicates that an error is reported when const is declared without assigning.Copy the code

Result when const constant is a variable... const foo = { x:0, y:1 } foo.x = 2 console.log(foo.x)Copy the code

So let’s think about what is the third result? Print 0? Or two? To summarize, const: 1. Only applies to block-level scopes, as does the let keyword 2. There is no variable promotion, but it must be declared in advance, as with let. 5. Consider that const defines a constant as a variable ????


Foo. X = 2 const foo. X = 2 const foo. X = 2 Let me explain that there is a concept: in the assignment process, we can divide into pass-value assignment and address assignment. Here we use address assignment, what is address assignment? Addressing: During assignment, a variable actually stores the address of the data (a reference to the data), not the original data or a copy of the data, for example

var obj= {

    "name": 'Joe'
}
var obj1 = obj
obj1.name='bill'Console. log(obj) // Li Si console.log(obj1) // Li SiCopy the code

Obj1 above,obj2 above is changed to li4 is called address assignment


Now, one of the things that comes to mind about the const keyword, we often say that const defines a constant. In es6, const represents a constant index of a value. In other words, an in-memory pointer to a variable’s name cannot change, but the value pointing to the variable can.

Second, the closure

What is a closure?

A closure is an inner function of an outer function (but note its properties).

1.1 features:

It has its own local scope.

2. It can access the outer scope of the function, the parameters, instead of the parameter object;

3. It can also access the global scope.

4. Parameters and variables are not collected by garbage collection (improper use of closures can cause memory leaks)

2. How closures work

1. Closures store references to external function variables, so updated values of external variables are always accessible

2. The closure can still execute after its external function is executed and returns a value (resident memory)

Benefits of closures

1. Save state (keep a variable permanently in memory)

2. Avoid global variables contamination

3. Allow private members

How do I use closures

Is this a closure?

function foo() {     
    var a = 2; 
    function bar() {         
        console.log( a ); // 2     
    } 
    bar(); 
} 
foo();
Copy the code

Is the above code a closure? The function bar() can access variable A in the outer scope, but it is not a closure.

function foo() {     
    var a = 2; 
    function bar() {          
        console.log( a );    
    } 
    returnbar; } var baz = foo(); baz(); // 2 -- That's what closures do, friend. The lexical scope of the function bar() has access to the inner scope of foo(). We then pass the bar() function itself as a value type. In this case, the function object referenced by bar is itself the return value. // After foo() is executed, its return value (that is, the internal bar() function) is assigned to the variable baz and baz() is called, actually just calling the internal function bar() with different identifier references. // bar() can obviously be executed normally. But in this case, it executes outside of its own lexical scope.Copy the code

The magic of closures is that they prevent foo() from being destroyed after execution. In fact, the inner scope still exists and has not been reclaimed. It is bar() itself that uses this internal scope. Thanks to the declared location of bar(), it has a closure that covers foo() ‘s internal scope, making it permanently viable for bar() to reference at any time thereafter. Bar () still holds a reference to that scope, and that reference is called a closure. The key aspect of closures is that after function A is executed, the variables or arguments in the function are not recycled and are referred to by other functions B (usually declared or defined by B in A). First: foo does not return a function after it executes, and there are no other functions around it that reference its variables. Its variables are recycled, so it is not a closure. To put it simply, when foo is executed, bar is executed. Although it refers to a in Foo, bar is executed before foo is executed, so after the whole process is executed, all local variables are not referenced by any other variables (objects) that currently exist and are destroyed by the system. Second: after foo is executed, the function it returns (bar) still references its variable A, so it’s a closure.

conclusion

Closures occur when a function can remember and access its lexical scope, even if the function is executed outside the current lexical scope. There are many more closures, but I’ll share them next time.


Here first today, if you have any questions, please leave a message and I will answer them. If the above is insufficient, please give directions!!