JavaScript-闭包(从一道面试题说起)

先看一段代码,并想出自己的答案:

    for(var i=0;i<5;i++){
        setTimeout(function(){
            console.log(i);
        },1000)
    }
    
    console.log(i);

不难得出,该题的答案是 5 5 5 5 5 5。
立即输出一个5,1秒后输出5个5。

如果这里想把答案变成:5 1 2 3 4 5。
那么,熟悉闭包的同学,很快可以得出一个这样的方法:

    for(var i=0;i<5;i++){
        (function(j){   //j = i
            setTimeout(function(){
                console.log(j);
            },1000)
        })(i);
    }
    
    console.log(i);

如果对定时器很了解的话,我们还可以用另一种方式:

    for(var i=0;i<5;i++){
        setTimeout(function(j){
            console.log(j);
        },1000,i)
    }
    
    console.log(i);

这里的setTimeout的第三个参数是可选项,表示提供给当前执行函数的其他参数

当然如果熟悉ES6语法,很快就会想到将var改成let,代码如下:

    for(let i=0;i<5;i++){
        setTimeout(function(){
            console.log(i);
        },1000)
    }
    
    console.log(i);

当然这种方法会报错,因为i值只在块级作用域内生效;
但是这种方法确实可以将定时器内打印出来的结果改为1 2 3 4 5

闭包,通俗的来讲就是一个函数可以访问另一个函数中的变量,避免变量被垃圾回收机制给回收。

最常见的闭包就是函数内部加一个子函数,通过子函数访问函数的局部变量。

你可能感兴趣的