zoukankan      html  css  js  c++  java
  • js 闭包理解

    看了一下网上闭包的概念及文章,对于这个问题,自己做一个梳理吧。

    • 问:闭包是什么?
    • 答:闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

    这个是我自身第一次碰到闭包的问题

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8"/>
    <title>闭包循环问题</title>
    <style type="text/css">
    p {background:#ccc;  300px; height: 100px;}
    </style>
    </head> 
    <body> 
    <p id="p0">段落0</p> 
    <p id="p1">段落1</p> 
    <p id="p2">段落2</p> 
    <p id="p3">段落3</p> 
    <p id="p4">段落4</p> 
    <script type="text/javascript">
    for( var i=0; i<5; i++ ) { 
    document.getElementById("p"+i).onclick=function() { 
    alert(i); //访问了父函数的变量i, 闭包 
    };
    };
    </script> 
    </body> 
    </html>
    

    如果你以前没这么用过的话,估计也会认为单击某个段落就会弹出这个段落相应的编号0,1,2,3,4。但实际上是都是弹出5;

    对于这个问题网上已经有很多讨论的博客了,他们给出了很多方法去实现弹出对应的编号。

    解决方法1:将变量i保存在对应的段落的某个属性上

    var pAry = document.getElementsByTagName("p"); 
    for( var i=0; i< 5; i++ ) { 
    pAry[i].no = i; 
    pAry[i].onclick = function() { 
    alert(this.no); 
    } 
    };
    

    解决方法2:加一层闭包,i 以函数参数形式传递给内层函数

    function test() {    
         var pAry = document.getElementsByTagName("p");    
         for( var i=0; i< pAry.length; i++ ) {    
          (function(arg){        
           pAry[i].onclick = function() {        
              alert(arg);    
           };    
          })(i);//调用时参数    
        }    
     }();
    

    对于这个产生的闭包问题,网上的说法是“变量i是以指针或者变量地址方式保存在函数中”;好吧,都和指针扯上关系了。。。。那就再探索一下吧。

    探索1,返回的都是10而不是20

    (function test() { 
    var temp =10; 
    for(var i=0; i< 5; i++ ){ 
    document.getElementById("p"+i).onclick=function() { 
    alert(temp); //访问了父函数的变量temp, 闭包 
    }
    };
    temp=20;
    })();
    
    

    探索2,返回一次10,接下去返回的都是20

    (function test() { 
    var temp =10; 
    for( var i=0; i< 5; i++ ) { 
    document.getElementById("p"+i).onclick=function() { 
    alert(temp); //访问了父函数的变量i, 闭包 
    }
    if(i===1){
    alert(temp);
    }
    };
    temp=20;
    })();
    

    由探索的1、2,可以得出结论:函数内部访问了与函数同级的变量,那么该变量是常驻内存的。访问该变量实质上是访问的是变量的地址;



    接着,又看了一篇关于“JS闭包中的this对象”的文章,继续来讨论一下,this这个问题吧。

    // js闭包this对象1
    var name = 'The Window';
    var object = {
        name : 'My Object',
        getNameFunc1 : function(){
            // return this.name;
            console.log(this);//object
            return function(){//闭包,访问的便是全局变量的了,this指windows
              console.log(this);//windows
              return this.name;  //The Window
            }
        },
        getNameFunc2 : function(){
              return this.name;//访问的是object
        },
        aa:function(){
          alert(22);
        }
    };
    alert(object.getNameFunc1()());//弹出“The Window”
    
    • 问: 那么为什么匿名函数没有取得其包含作用域的this对象呢?
    • 答:每个函数在被调用时都会自动获取两个特殊变量:this 和 arguments。 内部函数在搜索这两个变量时,指挥搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。
    不过通过下面的代码可以做到这一点(直接访问外部函数中的变量):
    // js闭包this对象2
    var name = 'The Window';
    var object = {
        name : 'My Object',
        getNameFunc : function(){
          var that = this;
          console.log(this);//输出的是object
          return function(){
            console.log(this);//输出的仍然是Windows
            return that.name;
          };
        }
    };
    alert(object.getNameFunc()());//弹出“My Object”
    

    不同之处在于把this对象赋给了一个that变量,即使在函数返回之后,that也仍然引用这object,所以会返回object。

    写了那么多闭包的东西,那也顺便再说一下闭包有神马用处吧;不然,一直捣乱那闭包可真是一个不好的家伙呢。

    看这样一典型的闭包的例子:

    function A(){
      var a=1;
      function B(){
        return a;
      }; 
      return B;
    };
    
    var C=A();//C取得A的子作用域B的访问接口
    console.log(C());//1 C能访问到B的父级作用域中的变量a 
    

    只要其他作用域能取到子作用域的访问接口,那么其他作用域就有方法访问该子作用域父级作用域的变量了。这样的话,如果以后需要访问某个函数里面的值得时候,就大大的有用咯。

    这些上面的很多代码其实也都是网上找的,我也只是把自己理解的,看的过程总结一下吧。

  • 相关阅读:
    mouseOver与rollOver
    排序二叉树
    发展
    bitmapData
    回调与事件
    遍历舞台上所有对象
    面向对象原则
    面向对象的三大特征(个人理解)
    面向对象出现原因以及意义
    OC语言BLOCK和协议
  • 原文地址:https://www.cnblogs.com/yldf55/p/4613692.html
Copyright © 2011-2022 走看看