• JavaScript闭包


    闭包其实就是利用了函数作用域和匿名函数的知识,当函数A执行结束时,一部分变量变量被B引用,被引用的变量不能释放,形成了所谓的闭包。这里有篇很好的文章,可以参考一下。
    下面看一个小例子:
    <script language="javascript" type="text/javascript">
    function show(){
        var n=3;
        setTimeout(function(){alert("first:"+n);},3000); //3秒后显示first:3
        alert("second:"+n); //显示second:3
    }
    show();
    function show2(){alert("第一个函数执行结束");}
    show2();
    </script>

    运行上面的函数后,首先alert显示"second:3",然后显示"第一个函数执行结束",3秒后显示“first:3”。

    仔细看一下,函数show执行结束的时候,变量n应该被释放了,内存里也就不存在了,怎么过了3秒还能显示出"first:3"呢?闭包恰恰就在此产生了,当函数show执行结束的时候,想要释放内存里的n,但发现变量n还在被一个匿名函数引用,要在3秒后调用,根据JavaScript闭包原理,内存里的n被保留了下来,于是在三秒以后仍然可以调用n。
    下面看几种写法的区别:

    function show2(content){
      alert(content);  //3秒后alert显示"test"
    }
    function show(content,delay_time){
        setTimeout("show2('"+content+"')",delay_time);
    }
    show("test",3000);
    仔细看一下上面这种写法不是闭包,只是普通的函数调用而已。
    function show(content,delay_time){
        setTimeout(function(){alert(content)},delay_time); //3秒后alert显示"test"
    }
    show("test",3000);

    这种写法就是闭包,虽然结果是一样的,但原理不一样。
    function show(content){
        function show2(){alert(content);}
        return show2;
    }
    var newshow=show("test");
    setTimeout(newshow,3000);  //3秒后alert显示"test"

    上面这种写法也是闭包,虽然结果都是一样的,但原理却不一样。这里面看到了函数也可以当作对象也传递,函数show执行后return show2,把函数show2赋值给newshow,然后3秒后,调用newshow对象,执行函数show2。
    仔细比较上面3种写法,如果能悟出一些道理就好,闭包有些时候的确难理解。
    稍复杂一点的例子:
    <script language="javascript" type="text/javascript">
    var show=null;
    (function(){
      var n=1;
      var show2=function(){
          alert(n++);
      }
      show=show2;
    })();

    show();  //显示1
    show();  //显示2
    show();  //显示3
    </script>

    上面代码中,又一次用了函数作为对象传递,n是匿名函数里的局部变量,外部是访问不到的。show是一个全局变量,应该访问不了变量n,但在函数show执行前,首先把函数匿名函数内部show2赋值给show,当后面函数show运行的时候,会调用show2的代码,而show2是可以访问n的,故结果显示为1、2、3。

    CSS代码:

    ul{ 600px; margin:0px auto;}
    ul li{ margin:1px 0px; }
    HTML代码:
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
    </ul>
    JavaScript代码:
    <script language="javascript" type="text/javascript">
    var li=document.getElementsByTagName("li");
    for(var i=0;i<li.length;i++){
       li[i].onclick=function(){alert(i);}
    }
    </script>

    运行后,不论点击哪一个li,都是alert提示“4”。这就是一个需要注意的地方:闭包允许内层函数引用父函数中的变量,但是该变量是最终值。闭包引用的变量i,是循环结束后的值,其实这是一个很常见的问题。
    比较常见的就是给li[i]添加属性值,比如li[i].n=i;还有就是用闭包方法解决,这个函数本身就是闭包,所谓用闭包来解决闭包的问题。代码如下:

    <script language="javascript" type="text/javascript">
    var li=document.getElementsByTagName("li");
    for(var i=0;i<li.length;i++){
       (function(index){
       li[index].onclick=function(){alert(index);}
       })(i); 
    }
    </script>
  • 相关阅读:
    vue-cli构建的项目手动添加eslint配置
    给通过canvas生成的二维码添加logo
    webpack打包时候去掉console.log配置
    gist.github.com 被墙无法访问解决办法
    axios.js 在测试机ios7.1的iphone4中不能发送http请求解决方案
    linux 系统的7个运行级别
    今天遇到了不能创建mysql函数
    今天测试大商创,遇到了 upstream sent too big header while reading response header from upstream
    mysql5.7 datetime 默认值为‘0000-00-00 00:00:00'值无法创建问题解决
    IE浏览器中判断IE版本
  • 原文地址:https://www.cnblogs.com/littlewriter/p/6050908.html
Copyright © 2020-2023  润新知