scope

Scope is the area in the program where variables are defined, and the location determines the lifetime of the variables.

Subdivision scope

  1. Global scope: Variables defined in the global scope can be accessed anywhere.
  2. Function scope: The scope that a function has
  3. Block-level scope: Scope accessible to a block in an area
        var b=10;
            function test(){
                var a=10;
            }
        console.log(b==a)
       //ReferenceError: a is not defined
Copy the code

The scope of a function is different from the scope of b. B is in global scope, a is in function scope.

   var b=10
   function test(){
      var a=10;
      console.log(b==a)
   }
  test()//true
Copy the code

Because b is global, it can be accessed even in functions.

if(ture){
    var a=10
}
console.log(a)/ / 10
Copy the code

How can a variable defined in a block-level scope be accessed globally?

  • This is because variables defined with VAR do not have block-level scope

Naming conflicts can easily occur if block-level scopes are invalid. To solve this problem, JavaScript since ES6 provides the let, const keyword to give variables block-level scope.

if(ture){
    let a=10
}
console.log(a)//ReferenceError: a is not defined
Copy the code

Small increase

Look at the problem first and get the output result

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

Do you think it’s 0 minus 9, or 10 tens? Let’s do the analysis and then we’ll figure it out.

First, introduce the concept of asynchrony. Asynchrony:

Callbacks refer to the fact that each task has one or more callback functions. After the completion of the previous task, the callback function will not be executed before the completion of the latter task. Therefore, the execution order of the program is inconsistent with the order of the tasks.

The function execution is asynchronous. Because we have to print I. So let’s first look at the code that executes the output I and in the first for loop, there’s no I in scope, so just follow the rules of scope and look up for the variable I, and when this function needs to execute, because it’s asynchronous it’s already done with the for loop and it’s 10. So when the function is executed, the output I =10. The result is 10 tens.

Obviously we want 0-9, so how can we improve?

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

Change var to let, because the variable defined by let creates the block-level scope independently. Each time let defines I to this block-level scope, so the output is 0-9.

  1. Since the above function is an asynchronous operation, we can make it execute immediately.
var arr = [];
for(let i = 0; i <10; i++){ arr[i] = (function(n){
        console.log(n)
    })(i)
}


/ / 0-9
Copy the code

closure

What is a closure

Closures are functions that can read variables inside other functions. The simple understanding is that when a function is saved externally, a closure is generated.

Guest officer, your little plum comes: if the teacher assigns homework, need two people to complete together, among them you need to write a function, calculate the number of running a function. As most of us can imagine, here’s how:

var count = 0
function test(){
    count ++
}
test()
Copy the code

Obviously, when test is executed, count increments by one. Unfortunately, your classmate also defined a variable called count, and the name of the variable conflicts. What should you do? Is there a method that holds a variable inside a function?

  • Look at the code
function add(){
    var num=0
 function a(){
     num++
     console.log(num)
 }
 return a
}

var result =add()
 result()/ / 1
Copy the code

Let’s first parse the code:

  1. Start by calling the add function and defining the variable result to hold its return value.
  2. The return value of the add function is also a function object: a function. That’s why we can call function A externally.
  3. Num ++ = num+ = num+ = num+ = num+ = num+ = num+ = num+ = num+ = num+ = num+ = num+ = num But the add function has already been executed? When a function executes, its scope ceases to exist, so why does it still get num?

When a function finishes executing, the recycle mechanism reclaims it.

However, after the add function is executed, the reclaim mechanism just wants to reclaim it. The function will say to the reclaim mechanism, “Although I have finished executing, Result has access and called function A that I returned. I don’t know when Result will execute function A, so I haven’t finished executing. So num can still be found in the add function.

Like, I had a lot of money, and I put some of it into a fund. I lost all my money gambling one day. Can you say I’m broke? Apparently not. I have some funds that I don’t know how much money they make, but I’m not broke.

That’s the concept of closures. A is in the scope of add, but it’s stored globally.

Defects in closures

1. Memory leak: The available memory space becomes smaller and the available engine space is insufficient

2. The browser is overloaded and requires more resources to execute

The drawbacks of closures are easy to understand. In the example above, because the add function cannot be reclaimed by the reclamation mechanism, the add function takes up memory for a long time, causing the engine to run out of available space and the browser to become overloaded, requiring more resources to execute.

Advantages of closures

Existence is reasonable, that is, there is a closure, that has the advantages of its existence:

1. Implement common variables

The above example turns num into a common variable

2. * * * * cache

Look at the code

function book(){
    var bo = 'Slam Dunk'
    var a= new Object
    a.readbook=function read(){
        console.log("I'm watching."+bo)
        }
    a.buybook=function buy(){
        bo=Romance of The Three Kingdoms
        console.log('I'll take it.'+bo)
    }
    return a
}
var me=book()
me.readbook()
me.buybook()
me.readbook()
// I'm watching the dunker
I bought the Romance of The Three Kingdoms
// I'm reading the Romance of The Three Kingdoms
Copy the code

The BO is cached

3. Achieve encapsulation

var call=function(){
    var name ='Fan Zuo'
    var me=function(){
    console.log('My name is:'+name)
    }
    return me
}
var callname= call()
callname()
Copy the code

Closures allow method instances to call variables outside the method. After the call function is executed, the function instance callName returned by call still has access to the name in the upper-level function. Callname calls a variable in a call. Callname is bound to name. Closures encapsulate external variables and method instances.

Well, this learning to share to this 🆗. If the article is wrong, please call and criticize!! See you next time 🙋 came ️