闭包

26 阅读1分钟

作用域闭包

定义:函数在他的作用域外执行,并且能记住并访问他自己的作用域

基本例子

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

var baz = foo();
baz();

第二种写法,只需要对函数类型的值进行了传递,并且该函数会在别处被调用都会形成闭包

function foo2() {
  var a = 2;
  function baz() {
    console.log(a);
  }
  bar2(baz);
}

function bar2(fn) {
  fn();
}

foo2();

写法3

var fn3;

function foo3() {
  var a = 2;
  function baz3() {
    console.log(a);
  }
  fn3 = baz3;
}

function bar3() {
  fn3();
}

foo3();
bar3();

将函数作为值到处传递也会形成闭包

在定时器,事件监听器,Ajax请求,跨窗口通信,webWorker或者其他异步任务中,只要存在回调函数都会形成闭包

function wait(message) {
  // 这里的timer函数就是wait函数里面保存的一个闭包
  setTimeout(function timer() {
    console.log(message);
  });
}
wait("hello closure");

应用场景

利用闭包解决循环遍历的问题

问题代码

// i5的值被遍历产生的定时器共享,最后输入的都是5
function wait(message) {
  // 这里的timer函数就是wait函数里面保存的一个闭包
  setTimeout(function timer() {
    console.log(message);
  });
}

解决方案

for (var i5 = 0; i5 < 5; i5++) {
  (function(i5) {
    setTimeout(function timer() {
      console.log(i5);
    });
  })(i5);
}

模块

1:形成私有变量

2:暴露公共API

function CoolModule() {
  var something = "cool";
  var another = [1, 2, 3];
  function doSomething() {
    console.log(something);
  }
  function doAnother() {
    console.log(another.join("!"));
  }
  return {
    doSomething,
    doAnother,
  };
}

var coolModule = CoolModule();

coolModule.doSomething();
coolModule.doAnother();