闭包

闭包

1.闭包的概念

MDN中描述,闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
init();

比如执行displayName(),diplayName的函数通过作用域链(

了解js的执行过程:https://www.cnblogs.com/listenMao/p/13329620.html

)得到name的值。通过 displayName()我们可以保存name的信息,这有赖于作用域链。js的词法作用域的特点是在函数创建定义时确定了作用域链,当一个内部函数(如displayName)变成一个闭包时,拥有 “他自身(如displayName)所形成的作用域链“。

2.闭包的缺点

function makeFunc() {
    var name = "Mozilla";
    function displayName() {//闭包
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();//myFunc指displayName;
myFunc();

.通常,函数的作用域及其所有变量都会在函数(makeFunc)执行结束后被销毁。但是,在创建了一个闭包(displayName)以后,这个函数的作用域(makeFunc)就会一直保存到闭包不存在为止。存在占用内存。

myFunc=null;//释放内存

3.闭包的使用

3.1模拟面向对象的方式

使用闭包来定义公共函数,并令其可以访问私有函数和变量,实际上可以使用es6的类或者es5的构造函数

var person=function(){
    //定义私有
    var name="";
    
    return {//暴露公共函数
        getName:function(){//
            return name;
        },
        setName:function(val){
            name=val;
        }
        
    }   
    
}
//建了一个词法环境,为2个函数共享。这2个公共函数是共享同一个环境的闭包。
var p=person();p.setName(6);p.getName();

3.2解决循环中类似输出i的错误

//例子1
//假设3个button,items为获取到的对应dom元素
var items=document.getElementsByTagName("button");
var len=items.length;
for (var i = 0; i < len; i++) {
            items[i].onclick = function () {
                console.log(i);//2,2,2
  }
}

//闭包解决
//这一种是立即执行形成闭包
for(var i = 0; i < len; i++) {
       (function(i){
        items[i].onclick = function () {
                
                console.log(i);//1,2,3
        }
        
        })(i);
           
}
//这一种是函数工厂,所有的回调不再共享同一个环境, make 函数为每一个回调创建一个新的词法环境
var make=function(i){
    return function () {//这里不能是有参数i
                
                console.log(i);//1,2,3
   }
}
for(var i = 0; i < len; i++) {
    
        items[i].onclick =make(i);
        
           
}
//例子2
for( var i=0;i<3;i++){
        setTimeout(function(){
            console.log(i); // 3,3,3
        }
        ,300);
  
}



//闭包解决
for( var i=0;i<3;i++){
    (function(i){
        setTimeout(function(){
            console.log(i); // 1,2,3
        }
        ,300);
    })(i);
}

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

posted @ 2020-07-23 23:43  这样就好了  阅读(160)  评论(0编辑  收藏  举报