js闭包

122 阅读2分钟

闭包:当内部函数被保存到外部时,会生成闭包。闭包的原理其实是内部函数或里面变量,被外部或者其他变量所引用,那么这个函数的当前作用域就无法被释放。闭包会导致原有作用域链不释放,造成内存泄漏。

function test(){
           var arr=[];
           for(var i=0;i<10;i++){
               arr[i]=function(){
                   document.write(i+" ");//赋值语句,函数引用的时候不会管后面函数体的内容,只有函数执行的时候才会读i的值
               }
           }
           return arr;
       }
       var myArr=test();
       for(var j=0;j<10;j++){
           myArr[j]();//函数执行,10个都公用一个执行期上下文
       }

解决方式

function test(){
           var arr=[];
           for(var i=0;i<10;i++){
               (function(j){
                   arr[j]=function(){
                       document.write(j+" ");
                   }
               }(i));
           }
           return arr;
       }
       var myArr=test();
       for(var j=0;j<10;j++){
           myArr[j]();//每执行一次循环都会产生一个新的立即执行函数,都会有自己的AO
       }

闭包的作用

  • 实现公有变量:例如函数加速器
function add(){
    var num=0;
    function a(){
        console.log(++num);
    }
    return a;
}
var myAdd=add();
myAdd();
myAdd();
  • 可以做缓存(存储结构):例如eater
    function test(){
            var food='apple';
            var obj={
                eatFood:function(){
                    if(food!=""){
                        console.log("I am eating "+food);
                        food="";
                    }else{
                        console.log("nothing is here!");
                    }
                },
                pushFood:function(myfood){
                    food=myfood;
                }
            }
            return obj;
        }
        var person=test();
        person.eatFood();
        person.pushFood("banana");
        person.eatFood();
  • 可以实现封装,属性私有化:例如Person()
function Person(name,wife){
    var prepareWife="xiaozhang";
    this.name=name;
    this.wife=wife;
    this.divorce=function (){
        this.wife=prepareWife;
    }
    this.changePrepareWife=function(target){
        prepareWife=target;
    }
    this.ayPrepareWife=function(){
        console.log(prepareWife);
    }
}
var person=new Person('du','xiaohong');
//在这个里面我们用person.prepareWife是找不到的,实行了一个属性的私有化,只能通过里面的方法来查看,里面的函数是可以看到这个属性的。并且可以使用。
  • 模块化开发,防止污染全局变量
var init1=(function(){
    var name=123;
    function callName(){
        console.log(name);
    }
    return function(){
        callName();
    }
}());
//互不影响
var init2=(function(){
    var name=45;
    function callName(){
        console.log(name);
    }
    return function(){
        callName();
    }
}());