闭包的含义和作用

1、根据JavaScript作用链,只能在内部访问到外部函数,通过闭包外部也可以访问内部变量。
2、js有垃圾清理机制,当一个对象使用后会自动清理,闭包可以使变量一直保存在内存中不会被清理。

正常情况下的访问 inner内部函数可以访问到变量a,但是outer访问不到inner的变量b
`
function outer (){

let a = 1;
function inner(){
    let b = 2;
    console.log(a); //1
}

}
`
使用闭包可以当函数执行完后变量仍然保持,将c保存到返回的inner1函数里,当outer1执行完后,c并不会被销毁而是返回到inner函数中。
调用outer1()后,返回了inner1赋值给closure。再执行closure可以即从外部获得变量c

function outer1(){
    let c = 99;
    //将变量返回到内部函数中
    return function inner1(){
        return c;
    }
}
let closure =  outer1();
let c1 = closure() // 99

用闭包来解决在循环中遇到的相关问题

当给多个元素绑定点击事件时使用循环遍历绑定的方法,点击绑定事件是异步回调的方法,所以会等到循环结束后才将i返回,以下会导致的问题就是无论点击哪个元素都只会打印3

<html>
<div id='div0'>div0</div>
<div id='div1'>div1</div>
<div id='div2'>div2</div>
<script>    
for(var a==0;a<3;a++){
    var div = document.getElementById('div'+n).addEventListener('click',function(){
        console.log(n)
    })
}
</script>
</html>

使用闭包,封装成一个独立的立即执行的匿名函数,将每次循环的i作为参数传进去,这样就可以在执行的时候取到当前i的值而不是循环结束后的值,分别点击div都是打印的是0,1,2

for(var i=0;i<3;i++){
    (function(n){
        var div = document.getElementById('div'+n).addEventListener('click',function(){
            console.log(n)
        })
    })(i)
}

同理setTimeout也是异步回调,如果没有使用闭包将它包裹会打印三次3

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

使用闭包后分别打印出0,1,2,3,4,5

for(let n=0;n<6;n++){
    (function(m){
        setTimeout(()=>{
            console.log(m)
        },0)
    })(n)
}

注意事项

使用闭包会导致内存外泄,因为当函数执行完后里面的变量并没有被垃圾清除机制清理,过多使用闭包会影响性能。


someone
218 声望7 粉丝

前端工程师