js中的闭包

在正文前面普及一下:

  js定义的变量分为全局变量和局部变量

  js可以在函数内部调取全局变量

  js函数外部不能取到函数内部定义的变量

  js平级函数不能相互读取函数内部定义的变量

  js闭包特殊之处就是函数2可以得到函数1的私有变量

--------------------------------------------------------------------------------------我是分割线------------------------------------------------------------------------------------------------------------------

什么是闭包?

百度给出的答案是:指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。

说实在的这句话反正我是没看懂,查阅书籍,发现闭包是指有权访问另一个函数作用域的变量的函数,常见创建闭包的方式就是在一个函数内部在创建另外的函数,

例如:

function funct1(){
    var num1="10";
    function  funct2(){
          alert(num1);   
    }
     return funct2;      
}    
var obj = funct1();
obj();

当然上面的例子funct1也可以直接返回一个匿名函数,

通过概念和案例,我对闭包的理解就是:能够获取函数内部私有变量的函数,

而在js的语法中,只有函数内部的子函数才能获取私有变量,所以闭包要写在函数内部,

闭包有两大作用:

  1、访问函数内部的私有变量,

  2、函数内部的私有变量不会被回收

1不用解释,2原因是将函数funct1返回的funct2函数赋给全局变量obj,此时funct2也是全局函数,而funct2函数有调用函数funct1的私有变量,级funct2函数依赖于funct1函数,因此funct1函数也会保留在内存里,不会被回收。

注意因为闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包会导致内存占用过多;闭包会在父函数外部改变父函数的私有变量,所以若将父函数当对象使用,把闭包当共有方法,把内部变量当成私有属性,这时切记请勿轻易改变父函数内部变量的值

说起闭包就需要引入作用域链,作用域链这种机制引入一个很大的副作用,即闭包只能获取包含函数中任何变量的最后一个值,如下面闭包:

function funct1(){
      var result = new Array();
      
     for(var i=0;i<10;i++){
        result[i]= function (){
                return i;
        }
    }
     return result;             
}  
var functs=funct1();
for(var i=0;i<functs.length;i++){
  console.log(functs[i]())
}

这个函数我们期望的是输出从0到9的数,可是事实并不是这样,它输出了10个10,也就是闭包输出的每次都是funct1函数变量i的最后一个值(10),这当然不是我们所期望的,这时需要引入一个匿名函数强制让闭包的行为符合预期:

function funct1(){
     var result = new Array();
       
    for(var i=0;i<10;i++){
        result [i] = function (num){
            return function(){
                  return num;    
            }        
        }(i);
    }
}
var functs=funct1();
for(var i=0;i<functs.length;i++){
  console.log(functs[i]())
}

此时运行此闭包就能完美输出从0到9的数,现在我们分析一下,这测版本中我们并没有直接把闭包赋值给数组,而是定义了一个匿名函数,并将立即执行匿名函数所得的结果赋给数组,这里的匿名函数有一个参数num,也就是最重要返回的值,在调用每个匿名函数时我们传入了变量i,由于函数参数是按值传递的,所以就会将变量i的当前值赋给num,而这个匿名函数内部有创建并返回了了一个访问num的闭包,这样result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了

当然this在闭包中也是比较好玩的,

var  num=10;

var obj= {
     num=20;
     alertNum;function(){
         return function(){
             return this.num;
        }
    }      
}

alert(obj.alertNum()());    //输出10

内部函数在搜索this和arguments两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量,不过把外部作用域中的this对象保存在一个闭包能够访问的变量里,就可以让闭包访问该对象了,如下面代码

var  num=10;

var obj= {
     num=20;
     alertNum;function(){
         var that = this;
         return function(){
             return that.num;
        }
    }      
}

alert(obj.alertNum()());    //输出20

 

posted @ 2017-08-03 15:08  朱格利斯  阅读(135)  评论(0编辑  收藏  举报