闭包

1.什么是闭包?

(1)函数嵌套函数

(2)内部函数可以引用外部函数的参数和变量

(3)参数和变量不会被垃圾回收机制所收回。因为内部函数bbb还在被引用着,所以需要长期驻扎在内存中。

function aaa(a){
  var b=5; 
  function bbb(){
     alert(a);
     alert(b);  
}   
}

aaa();//a和b都是可以访问的到的

这就是闭包

function aaa(){
    var a = 5;
    function bbb(){
        alert(a);
    }
    return bbb;
}

var c = aaa();//因为aaa()函数返回的是bbb

c();//此时c()就相当于bbb()

返回的结果就是:5

 

2.什么是垃圾回收机制?

//JS中的垃圾回收机制

function aaa(){
    
    var a = 1;
    
}

aaa();

变量a会被JS中垃圾回收机制收回,就不存在了。

 

 3.闭包有什么好处?应用在哪里?

好处:(1)希望一个变量长期驻扎在内存当中
   (2)避免全局变量的污染
        (3)私有成员的存在

栗子1:全局变量的污染:a是全局变量

var a = 1;
function aaa(){
    a++;
    alert(a);
}

aaa();  //2
aaa();  //3

alert(a);//3

栗子2此时a是局部变量,每执行一次,就进入垃圾回收机制,所以每次执行aaa()函数,结果都是2

function aaa(){
    var a = 1;
    a++;
    alert(a);
}
aaa();  //2
aaa();  //2

栗子3:利用闭包,变量a是局部变量

function aaa(){
    var a=1;
    return function(){
        a++;
        alert(a);
    }
}

var b=aaa();
b();  //2
b();  //3
alert(a); //a is not defined,因为a不是全局变量,访问不到a

用法:
1.模块化代码
2.在循环中直接找到对应元素的索引

栗子4:模块化代码

function aaa(){
    alert(1);
}
aaa();

//这两个函数结果是一样的,不同的是下面的(function(){
    alert(1);
})是一个函数表达式

(function(){
    alert(1);
})();
var aaa=(function(){
    var a=1;
    return function(){
        a++;
        alert(a);
    }
})();
aaa();  //2
aaa();  //3

栗子5有私有成员的存在,变量a,函数bbb(),函数ccc()

var aaa=(function(){
    var a=1;

    function bbb(){
        a++;
        alert(a);
    }

    function ccc(){
        a++;
        alert(a);
    }

    return {
        b:bbb,
        c:ccc
    }
})();

aaa.b();  //2
aaa.c();  //3,为什么是3呢?因为a相对于bbb函数和ccc函数,是全局变量,所以函数bbb执行后,a=2了,再执行ccc函数就是3了

 栗子6:在循环中直接找到对应元素的索引

方法一:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
window.onload = function(){
    var aLi = document.getElementsByTagName('li');
    for(var i=0;i<aLi.length;i++){
        (function(i){

            aLi[i].onclick=function(){
                alert(i);
            }
        })(i);//将i参数传进去,存在内存中。
    }

};

</script>
</head>

<body>
<ul>
    <li>11111111111</li>
    <li>11111111111</li>
    <li>11111111111</li>
</ul>
</body>
</html>

这样得到的结果是,点击哪一个按钮,就弹出那个位置的索引

方法二:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>索引</title>
    <script>
        window.onload=function(){
            var lis=document.getElementById('test').getElementsByTagName('li');
            for(var i=0;i<lis.length;i++)
            {
                lis[i].index=i;
                lis[i].onclick=function(){
                    alert(this.index);
                };
            }
        }
    </script>
</head>
<body>
    <ul id="test">
        <li>这是第一条</li>
        <li>这是第二条</li>
        <li>这是第三条</li>
    </ul>
</body>
</html>

 

 

4.闭包需要注意的地方?

在IE下有可能闭包引发的内存泄露问题及解决方案

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重无论多少内存,迟早会被占光。

memory leak会最终会导致out of memory!

内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。 

    内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete)结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出. 

栗子7:这样就会引发内存泄漏,除非关掉浏览器。

window.onload = function(){
	var oDiv = document.getElementById('div1');
	
	oDiv.onclick = function(){
		alert(oDiv.id);
	};

 

为什么这样会引发内存泄漏?

因为dom已经获取到了div1的节点,下面的oDiv的属性onclick里面的函数又存在访问oDiv的属性id,这样就形成了内存泄漏。

解决方案:

 第一种:

window.onload = function(){
    var oDiv = document.getElementById('div1');
    
    oDiv.onclick = function(){
        alert(oDiv.id);
    };
    
    window.onunload = function(){
        oDiv.onclick = null;
    };
    
};

onunload 事件在用户退出页面时发生。页面退出时,将onclick属性释放。

 

第二种:将需要用的id先获取到,最后将oDiv释放。

window.onload = function(){
    var oDiv = document.getElementById('div1');
    
    var id = oDiv.id;
    
    oDiv.onclick = function(){
        alert(id);
    };
    
    oDiv = null;
    
};

 

posted @ 2016-07-22 15:51  GumpYan  阅读(166)  评论(0编辑  收藏  举报