闭包的理解

直接上案例,是摘自《javascript面向对象编程》中的一个案例。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
    <h1 id="h1">
      这里一共创建了3个闭包,他们都指向了一个共同的局部变量i。但是闭包并不会记录他们(变量i)的值,他们(变量i)所拥有的只是一个一个i的链接(即引用),因此只能返回i的当前值。由于循环结束时i=3,所以这三个函数都指向了这一共同值。
    </h1>
</body>
<script>
  function f1() {
    var a = [];
    var i;

    for(i=0;i<3;i++) {
      a[i] = function () {
        return i; 
      }
    }
    return a;
  }
  var a = f1();
  console.log(a[0]());// 3
  console.log(a[1]());// 3
  console.log(a[2]());// 3

  // 解决办法1:
  // 不直接创建一个返回i的函数,二十将i传递给一个自调函数。
  // 在该函数中,i 就被赋值给了一个局部变量x,这样一来,每次迭代中的x就会拥有各自不同的值了
  // 实现的关键,是在中间函数内,将i的值“本地化”,存储到本地,中间函数的参数也是本地化数据
  // 下面函数f2最终 return 的是x,x 是函数b[i]的形参,形参是存储b[i]作用域的,当被传入实参i的时候,x分别是1,2,3,return 的也是传入的实参 1,2,3,只要将 i 的值传入函数b[i],i 与函数 f2的 返回值就没有直接关联了。
  function f2() {
    var b= [];
    var i;
    for(i= 0;i<3;i++) {
      b[i] = (function(x){
        return function() {
          return x
        }
      })(i) 
    }
    return b;
  }

  var b = f2();
  console.log(b[0]());// 0
  console.log(b[1]());// 1
  console.log(b[2]());// 2


  // 不使用自调函数的写法
  function f3() {
    var b= [];
    var i;
    var mkClosure = function (x) {
      return function () {
        return x;
      }
    }
    for(i=0;i<3;i++) {
      b[i] = mkClosure(i)
    }
    return b;
  }

  var c = f3();
  console.log(c[0]());// 0
  console.log(c[1]());// 1
  console.log(c[2]());// 2

</script>
</html>

 

posted @ 2018-03-07 16:36  ifIhaveWings  阅读(173)  评论(0编辑  收藏  举报