zoukankan      html  css  js  c++  java
  • js闭包问题

    首先想要理解闭包,必须先要理解js中的作用域问题。

    作用域不过就是两种,一种是全局变量一种是局部变量。

    例如:

    var n = 66;
    function fn(){
       alert(n);
    }
    fn();

    这段代码中的n就是定义的全局变量。

    function fn(){
       var n = 66;
       alert(n);
    }
    fn();

    而这段代码中的n就是局部变量,而内部变量在函数外部是不能访问的。注意:定义局部变量的时候必须要写var,不然n就会变成你定义的全局变量。

    那么如何从外部函数来取内部函数的变量呢?

       function fn1(){
        n=66;
        function fn2(){
          alert(n);
        }
        return fn2;
      }
      var result=fn1();
      result(); 

    运行这段代码,浏览器会弹出66.我们用过return的方式在fn1中吧fn2 return到全局变量中,我们把fn2作为返回值的这种方式来实现f1外部读取它的内部变量。这样整个内部和外部形成了一个作用域链,只要fn1调用不清楚,整个作用域链中的所有变量都保留在内存不消失。这个性质也造成了js代码严重的性能问题,闭包是一把双刃剑,他能实现很多的高级应用,但是如果处理不好就会造成全局污染,让代码的运行速度大打折扣。

    什么是闭包呢?

    我个人的理解,知道是关于外部函数访问内部的局部变量,那么这个函数就形成闭包。闭包也就是能够读取其他函数内部变量的函数。

    闭包在实际工作中的用途是什么呢?下面我们来看一段这样的代码:

    var s=[];
    function foo(){for (var i=0;i<3;i++){
            s[i]=function(){
                alert(i)
            }
        }
    };
    foo();
    s[0](); // 3
    s[1](); // 3
    s[2](); // 3

    这段代码会连续跳出三个3.如果我们有一个需求就是每次弹出的数字是出现的次数,那么这段代码就有问题了,因为我们都知道代码是按顺序加载的,当我们执行s[0]的时候我们上面的循环代码已经执行完了,也就是说输出所有的i都只能是3,因为代码已经执行完了。如果我们想来实现上述需求就必须要把所有循环的i存起来,这时候闭包就有用了,我们可以形成一个作用域链把所有的i都存到作用域链中,这样只要执行所有的i都没有释放也就能取到所有的i的值的,下面来看代码。

    var s=[];
        function foo(){
            for (var i=0;i<3;i++){
                (function(index){
                    s[i]=function(){
                        alert(index);
                    }
                })(i);
            }
        };
        foo();
    s[0](); // 0
    s[1](); // 1
    s[2](); // 2

    这种写法有一个好处,仔细的同学能看到我在内部写了一个匿名函数。我们创建了一个匿名的函数,并立即执行它,由于外部无法引用他的内部变量,因此在函数执行完之后会立即释放资源,关键是不污染全局变量。

    最后再说闭包最后的一个用途:

    var person = function(){    
        //变量作用域为函数内部,外部无法访问    
        var name = "default";       
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    }();    
         
    alert(person.name);//直接访问,结果为undefined    
    alert(person.getName()); //结果为default    
    person.setName("abruzzi");  
    alert(person.getName());//结果为abruzzi

    如上述代码,我们可以利用闭包进行函数封装,我们通过return方式来形成作用域链,在我们调用person方法时候才能访问,而直接访问是不能访问的,因为var定义的局部变量,所以我们取不到name的值而我们定义的函数getName里面return name;这个方法把name返回,在person方法里面也是一个return,所以我们可以通过getName的方法来访问person里面的name值。

  • 相关阅读:
    Django_rest_framework
    Django之FBV / CBV和中间件
    数据库之MySQL补充
    数据库之Python操作MySQL
    数据库之MySQL进阶
    数据库之初识MySQL
    2-3、配置Filebeat
    2-2、安装Filebeat
    2-1、FileBeat入门
    5、Filebeat工作原理
  • 原文地址:https://www.cnblogs.com/jcscript/p/5638754.html
Copyright © 2011-2022 走看看