[Closures and let and val] Comprehensive understanding and explanation of closures and let and val

1. What is a closure

A closure is a function that has access to variables in the scope of another function. The most common way to create a closure is to create another function within a function. The created function can access the local variables of the current function.

Second, the characteristics of the closure

  • (1) Make it possible to access the internal variables of the function externally

  • (2) Variables will be resident in memory

  • (3) The use of global variables can be avoided to prevent global variable pollution;

3. The advantages and disadvantages of closure

  • Benefits: Variables inside other functions can be read and kept in memory all the time.

  • Disadvantages: May cause memory leaks or overflows.

4. Closures have two common uses

  • (1) The first use of closures is to enable us to access variables inside the function outside the function. By using closures, variables inside the function can be accessed externally by calling the closure function externally. This method can be used to create private variables.

  • (2) Another use of the closure is to keep the variable object in the function context that has already run in memory, because the closure function retains the reference of the variable object, so the variable object will not be recycled.

For example, AFuncif there is a function inside function BFunc, and function BFunccan access AFuncvariables in function , then function BFuncis a closure.

function AFunc() {
    
    
    let aaa = 'aaa';
    return function BFunc () {
    
    
        console.log('闭包内console:', aaa);
    }
}
AFunc()(); // '闭包内console:aaa'

In JS, the meaning of closure is to allow us to indirectly access the variables inside the function. Classic interview questions: the problem of defining functions es5solved by using closures in loopsvar

for (var i = 1; i <= 10; i++) {
    
    
    setTimeout(function loop() {
    
    
        console.log(i)
    }, i * 500); // 每500ms执行一次
}

First of all, because setTimeoutis an asynchronous function, all the loops will be executed first. At this time, iis 11, so a bunch of 11 will be output. There are three solutions:

The first way is to use closures

for (var i = 1; i <= 10; i++) {
    
    ;
    (function(j) {
    
    
        setTimeout(function loop() {
    
    
            console.log(j)
        }, j * 500); // 每500ms执行一次
    })(i)
}

The above is equivalent to

function func(i) {
    
    
	// 此时的Loop形成了闭包
	setTimeout(function loop() {
    
    
        console.log(i)
    }, i * 500); // 每500ms执行一次
}
for (var i = 1; i <= 10; i++) {
    
    ;
    func(i); // 此时的i传入func作为func函数的参数,等同于他内部的变量
}

In the above code, the immediate execution function is first used to pass i into the function. At this time, the value is fixed on the parameter j and will not change. When the closure is executed next time, the variable j of the external function can be used loop. , so as to achieve the purpose.

The second is to use setTimeoutthe third parameter of the , which will be looppassed in as a parameter of the function.

for (var i = 1; i <= 10; i++) {
    
    
    setTimeout(
	    function loop(j) {
    
    
	        console.log(j)
	    },
        i * 500,
        i // 作为loop函数的参数传入,等同于内部自定义了变量,因此可以正确记录数字i的自增
    )
}

The third way is to use letdefine i to solve the problem, which is also the most recommended way

for (let i = 1; i <= 10; i++) {
    
    
    setTimeout(function loop() {
    
    
        console.log(i)
    }, i * 500)
}

PS: letHow varis it different from

You can also refer to: https://blog.csdn.net/qq_43145310/article/details/125737211
The biggest difference between let and var is that the scope of let declaration is block scope, while the scope of var declaration is function scope. let does not allow repeated declarations. Function scope > block scope.

Both var and let are used to declare variables, the difference is:

  • (1) letThe declared variable cannot be declared repeatedly, but varcan

  • (2) letDeclared variables cannot be variable promoted, but varcan

    • When vardeclaring one var变量, the variable is hoisted to the top of the scope, however 赋值的部分不会提升.
console.log(a);
var a = 'aaa';
    • The a variable can be output before the statement declaring a, and the value is undefined, this is the variable promotion, and letthe variable cannot be promoted when using the declared variable.
  • (3) varIt is function scope and letblock scope

    • If a variable is declared in a function var, the variable is valid throughout the function. For example, if vara variable is declared in a for loop, it can also be used outside the for loop. But letthe scope is a block scope, which is only valid in the scope. For example, leta variable declared in a for loop cannot be accessed outside the for loop.
      insert image description here
      insert image description here
  • (4) The variables declared in the global environment letdo not belong to the top-level object (failed to verify successfully, to be confirmed)

    • The top-level object, 浏览器referred to in the middle window, node环境refers to globalthe object in the middle.
    • varThe declared variables belong to the top-level object window, so they can be accessed through the window. variable name, and letthe constdeclared variables cannot be accessed in this way.
var name = 'Jerry'; 
console.log(window.name); // 'Jerry' 
let age = 35; 
console.log(window.age);  // undefined

insert image description here

5. Points to note when using closures

  • (1) Because the closure will make the variables in the function be stored in the memory, the memory consumption is very large, so the closure cannot be abused, otherwise it will cause performance problems of the web page, and may cause memory leaks in IE. The solution is, 在退出函数之前,将不使用的局部变量全部删除.

  • (2) 闭包会在父函数外部,改变父函数内部变量的值. So, if you use the parent function as 对象(object)a use, the closure as its public method (Public Method), and the internal variable as its private property (private value), then you must be careful not to change the parent function casually The value of the internal variable.

Guess you like

Origin blog.csdn.net/hzxOnlineOk/article/details/129953753