可能大多数人平时大量写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) }