初识闭包:在for循环中的应用

起因是想写两个嵌套的for循环,然后在里层的循环中读取到外层循环的变量值。以为会读取到0 1 2 3 4这样,但结果都是外层循环中最后一次循环到的值。
为了解决这个问题,需要用到匿名函数、立即执行函数与闭包。

  1. 匿名函数:没有命名的函数,因为直接执行了,所以不需要函数名来调用;
  2. 立即执行函数:能够立即运行的函数,也叫IIFE;
  3. 闭包:函数里有函数的函数。

立即执行函数的写法一般为:(fun...)()或者(fun...()),刚好这种函数嵌套函数的写法,也称之为闭包。

初始代码:

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

使用立即执行函数后:

  for (var i = 0; i < 5; i++) {
    (function(i) {
      setTimeout(function() {
        console.log(i);  // 0 1 2 3 4
      },1000)
    })(i);
  }

换一种写法:

  for (var i = 0; i < 5; i++) {
    setTimeout(
      (function(i) {
        return function (){
          return console.log(i)  // 0 1 2 3 4
        }
      })(i)
    ,1000)
  }

无论是写在setTimeout中还是将之包裹起来,初衷都是为了让JS在执行for循环的时候,立即运行带有i参数的函数,从而保存了当时i的值。
在这个问题中主要运用的是立即执行函数,关于立即执行函数的更多写法可以参考这篇文章:浅谈匿名函数和闭包

JavaScript在ES6之后新增了let声明,这样就有了另外一种途径来解决这个广泛的问题:

  for (let i = 0; i < 5; i++) {
    setTimeout(function() {
      console.log(i);  // 0 1 2 3 4
    }, 1000)
  }

因为let声明的变量有了自己的块级作用域,并不会因上次的赋值而改变,但是缺点也有:不支持IE11以下的浏览器。

 居中容器的思考
解决两个window.onload冲突问题 
上一篇:居中容器的思考
下一篇:解决两个window.onload冲突问题