javascript中闭包的一些理解

myux8313 3年前
   <p>闭包是javascript中绕不开的话题,关于闭包的一些概念和应用,这方面资料比较多,在此就不再赘述。众所周知,闭包的一个作用就是 让一些变量始终保持在内存中 ,在此我用一些实际代码对这句话作进一步的理解。</p>    <pre>  <code class="language-javascript">demo1:  function closure(){    var n = 0;    function test() {      console.log(++n);    }    test()     test()   }  a(); //输出1,2(这个很好理解,不多说)    demo2:</code></pre>    <pre>  <code class="language-javascript">function test(){      var i=0;      return function(){          console.log(i++);      }      }      var fn = test();      fn(); //输出0      fn(); //输出1</code></pre>    <p>上述代码中,fn就是执行函数test()返回的匿名函数。由于fn又是一个全局变量,生命周期一直存在,且这个匿名函数引用了父函数test里面的一个局部变量,所以变量i的状态会被一直保存.</p>    <p>demo3:</p>    <pre>  <code class="language-javascript">function test(){      var i=0;      return function(){          console.log(i++);      }  }  test()(); //输出0  test()(); //输出0</code></pre>    <p>上述代码中,执行test()返回的是其内部的匿名函数,但是执行完test()()以后,该匿名函数的生命周期已经结束,所以变量i的状态没有得到保存。</p>    <p>最近在简书上读到一篇有趣的文章,其中一些代码如下:</p>    <pre>  <code class="language-javascript">for (var i = 0; i < 5; i++) {   setTimeout((function(i) {      console.log(i);    })(i), i * 1000);  }   //输出0,1,2,3,4</code></pre>    <p>上述代码中有一个setTimeout()函数,其使用格式为setTimeout(func,time),意思是至少过time时间后,执行func。有了这样的认识后,我们可以把func等价成:</p>    <p>(function(i){console.log(i)})(i)这个自执行函数。所以这个事情分两步,首先每次循环自执行函数肯定会立即执行一次,会依次输出1,2,3,4。其次,每过time时间,执行一次func,但是在上述代码中,func等价于一个立即执行函数,没有返回值,故什么也不会做。</p>    <p>如果把上述代码改成这样:</p>    <pre>  <code class="language-javascript">for (var i = 0; i < 5; i++) {    var j=7;    setTimeout((function(i) {      console.log(i);      return function(){         console.info(j++);      }    })(i), i * 1000);  }</code></pre>    <p>上述代码会依次输出0,1,2,3,4, 7,8,9,10,11(结合这个例子理解上一个问题,就容易多了)</p>    <p>如果把上面的代码改成这样呢?</p>    <pre>  <code class="language-javascript">for (var i = 0; i < 5; i++) {    setTimeout(function() {      console.log(i);    }, i * 000);  }</code></pre>    <p>运行上面的代码会输出5个5(这一点现在可以理解了吧),有人不解的是为什么是每隔一秒输出5而不是隔五秒输出5。setTimeout(func,time)这个函数延迟执行的只是func里面的动作,而time的值是不存在延迟的。上面执行for循环,相当于:setTimeout(func,1000),setTimeout(func,2000) .... 第一次setTimeout执行的时候等了一秒(准确地说,至少要等一秒),第二次setTimeout执行的时候等2秒,但是前面第一次执行的setTimeout函数时,已经等了一秒,所以只需再等一秒就可以立即执行了。在这里,需要弄明白的是,setTimeout函数延迟执行的时间,起点是从time开始赋值的时候计算的,不是从上一个setTimeout函数执行完开始算的。</p>    <p> </p>    <p>来自:https://segmentfault.com/a/1190000008571702</p>    <p> </p>