我理解的闭包

366 阅读2分钟

我理解的闭包,欢迎来喷

定义

  • js函数会用到外部的变量,那么这个函数加变量就叫闭包 在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

为什么要使用闭包

那就得从局部和环境变量的优缺点说起

  • 全局变量:可以重复用、但是会造成全局污染而且容易被篡改。
  • 局部变量:仅函数内使用不会造成全局污染也不会被篡改、不可以重复用。
  • 所以,全局变量和局部变量的优缺点刚好相对。闭包的出现正好结合了全局变量和局部变量的优点。

何时使用闭包

  • 希望重复用一个对象,但是又保护对象不被污染篡改时。

使用形式

  • 返回一个函数,这种使用的情景是最多的
var a  = 1;
function foo(){
  var a = 2;
  // 这就是闭包
  return function(){
    console.log(a);
  }
}
var bar = foo();
// 输出2,而不是1
bar();
  • 作为函数的参数传递:无论通过何种手段将内部函数传递到它所在词法作用域之外,它都会持有对原始作用域的引用,无论在何处执行这个函数,都会产生闭包。
var a=1;
function foo(){
    var a=2;
    function baz(){
        console.log(a);
    }
    bar(baz);
}
function bar(fn){
    //这就是闭包
    fn();
}
//输出2,而不是1
foo();
  • 回调函数:在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就是在使用闭包
//定时器
setTimeout(function timeHandler(){
    console.log('timer');
},100)

//事件监听
$('#container').click(function(){
    console.log('DOM Listener');
})

遇到的问题

for(var i = 1; i <= 5; i ++){
  setTimeout(function timer(){
    console.log(i)
  }, 0)
}
//为什么会全部输出6?如何改进,让它输出1,2,3,4,5?(方法越多越好)
  • 在循环使用中把var 改成 let
for(var i = 1; i <= 5; i ++){
  setTimeout(function timer(){
    console.log(i)
  }, 0)
}