# 题目描述
闭包的一个小案例
每1秒输出一个j,  j递增 —— j初始值为1
1,2,3,4...
# 💪实现
下面这样写,就是一个for循环执行三次,for里面都是立即执行函数,所以直接放了三个setTimeout到了任务队列里,同时,这三个都是设置的一秒后执行,
所以最后三条语句是同时输出,没有实现每1秒输出一次的需求
但此时
j是闭包的,每次循环递增, 所以三条语句中的j是实现了需求的,
for(var i = 0; i < 3; i ++){
  ((j) => {
    setTimeout(() => {
      console.log("第" + j + "次");
    }, 1000);
  })(i);
}
 1
2
3
4
5
6
7
2
3
4
5
6
7
所以要控制三条语句按1秒的间隔输出,那就要在setTimeout的执行时间上做文章了
for (let i = 1; i <= 4; i++) {
  ((j) => {
    setTimeout(() => {
      console.log(j);
    }, j * 1000);
  })(i);
}
 1
2
3
4
5
6
7
2
3
4
5
6
7
上述的代码就可以实现我们的需求了~
# 扩展
下面的代码输出 1,2,3,4,每次输出间隔一秒
TIP
因为let绑定 for 循环,let有自己的作用域块,会将其重新绑定到每一次的迭代中,保证每次迭代结束都会重新赋值
for( let i = 1; i <= 4; i ++){
  setTimeout(() => {
    console.log(i);
  }, i * 1000);
}
 1
2
3
4
5
2
3
4
5
但下面的代码输出5,5,5,5,每次输出间隔一秒
TIP
var 没有自己的作用域块,所以循环变量就会后一个覆盖前一个,循环完毕只有一个值输出 —— 也就是最后一次i的值;
for (var i = 1; i <= 4; i++) {
  setTimeout(() => {
    console.log(i);
  }, i * 1000);
}
 1
2
3
4
5
2
3
4
5
# ✋ 手写一个闭包
- 闭包(Closures)是一个能够读取其他函数内部变量的函数
 - 优点:使外部能访问到局部的东西 —— 让外部通过子函数来访问该函数里的局部变量
 - 缺点:使用不当容易造成内存泄漏的问题
 
console.log("请输入a: ");
const a = Number(readline());
console.log("请输入a: ");
const b = Number(readline());
function myClosures(a) {
  let inside = a;
  return () => {
    return inside + b;
  };
}
console.log("a + b = ", myClosures(a)(b));
 1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
再稍微扩展一下 —— 可以实现公共、私有作用域控制
既然闭包可以对外提供访问内容变量的方式,就可以用这个特点实现类似 public private 作用域的需求
代码如下所示 👇
// 实现private对象
// 外部是访问不到data这个对象的
// 可以使用该data对象来存储一些私有的数据 —— 键值对的形式
var mydata = (function () {
  var data = {};
  return function (key, val) {
    if (val === undefined) {
      console.log("data: ", data);
      return data[key];
    } else {
      data[key] = val;
      console.log("data: ", data);
      return data[key];
    }
  };
})();
console.log(mydata("x")); // data没有"x"这个key, 返回undefined
console.log(mydata("x", 1)); // 在data对象中设置一个键值对,"x" = 1, 然后返回"x"对应的val
console.log(mydata("x")); // data中有"x"对应的val, 直接返回对应val的值
/**
  data:  {}
  undefined
  data:  { x: 1 }
  1
  data:  { x: 1 }
  1
*/
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
闭包的四个应用场景
- 防抖
 - 节流
 - 封装私有变量
 - 模拟私有方法