JS

可能大多数人平时大量写js代码,但是对闭包还是模模糊糊。本文记录自己学习闭包的一些知识点。

function foo() {
    var a = 2;
    function bar() {
        console.log(a)
    };
    return bar;
}

var result = foo()  // result就是foo返回的bar
result() // 调用了bar,成功访问了函数作用域中的变量a

以上就是一个闭包的代码。foo()执行后,foo()内部作用域会被销毁,JS垃圾回收器回收无用的空间,释放内存。但是由于闭包的存在,会使它一直存在。因为bar()本身在使用这个作用域。bar()对foo()作用域的引用就叫闭包。

传递函数的方式观察闭包,通过内部函数baz传递过来,由于baz涵盖了foo作用域,所以能够访问到a

function foo() {
    var a;
    function bar() {
        console.log(a)
    }
    baz(bar)
}

function baz(fn) {
  fn()   //这就是闭包
}

在平时编码过程中,闭包随处可见。比如将函数作为参数到处传,那么就会在这些函数调用中找到闭包。比如平时常见的定时器。

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

以上代码,我们期望它能每一秒依次输出1-5,但是其实它的结果是 6 个 6,这是由于 i 其实是一个全局作用域,并没有在每次循环中存储。for循环到最后i的结果是6。

我们可以通过闭包来解决这种问题,将每次循环的i值传入闭包函数中进行存储。

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

es6中新增了let,也可以解决以上问题,更加简便。

for(let i=0; i<=5; i++) {
    setTimeout(function timer() {
        console.log(i)
    }, i*1000)
}
原文地址:https://www.cnblogs.com/zhoujin-Jojo/p/13848742.html