简单点说,闭包就是函数嵌套函数,其中外部函数可以引用内部函数的参数和变量。
function aaa(a){ var b = 5; function bbb(){ alert(a); alert(b); } } var bbb = aaa(3); bbb();//result : 3 5垃圾回收机制
垃圾回收机制:在闭包的情况下,参数 a 和 变量 b 是不会被垃圾回收机制回收的,因为内部的闭包还在引用着外部的变量。
//js 中的垃圾回收机制 function aaa(){ var a = 1; } //当这个函数调用完了之后,函数里面的变量就会被垃圾回收机制回收 aaa(); //垃圾回收机制测试 function aaa(){ var a = 5; function bbb(){ alert(a); } return bbb; } //这个时候 aaa 函数已经执行完毕了,这个时候 c //代表的是 bbb 这个函数 var c = aaa(); //这里执行的其实是bbb(); c();// result : 5 //由上述的结果可知:闭包内的变量并不会被垃圾回收机制回收闭包可以做到私有成员,私有方法,减少全局变量的污染来达到你想要的效果。
var a = 1; function aaa(){ a++; alert(a); } aaa();//2 aaa();//3 //在这里 a 是全局变量所以我们可以在函数内部使其自增 //如果我们把 a 变成一个局部变量 function aaa(){ var a = 1; a++; alert(a); } aaa();//2 aaa();//2 //在这里 a 只是函数内部的一个局部变量,当我们调用函数的时候不能实现其自增。如何做到让 a 既是局部变量同时我们在外部调用的时候让 a 又可以累加?这就是我们的闭包可以做到的。
写法一:
function aaa(){ var a = 1; return function (){ a++; alert(a); } } var c = aaa(); c();//2 c();//3 //可以看到当我们在使用闭包的写法的时候,可以做到让 a 既是局 //部变量同时在外部调用函数时,又可以实现其累加写法二:(改写为函数声明)
//改写为函数声明 (function (){ var a = 1; return function (){ a++; alert(a); } } )()();也可以像下面这样改写:
var aaa = function (){ var a = 1; return function (){ a++; alert(a); } }(); aaa();//2 aaa();//3 //这就是模块化代码,通过减少全局变量的污染来达到想要的效果模块化代码模型
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用闭包来解决这个问题:(第一种写法)
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); } }用闭包来解决这个问题:(第二种写法)
window.onload = function(){ var aLi = document.getElementsByTagName('li'); 第二种写法 for(var i=0; i<aLi.length; i++){ //当你点击的时候,我这个里面已经执行完毕了,所以这个 i 已经 //驻扎在内部了,所以点击的时候,你调用的 i 是内部的函数已经 //存在内存中的 i了,而不是外面的 i aLi[i].onclick = (function(i){ return function(){ alert(i); } })(i); } }在 ie 下使用闭包会引发内存泄漏。
引发内存泄漏的条件:当一个变量,这个变量是由获取一个 dom节点,或者是一个宿主对象的时候,他的一个属性,比如说 onclick 去引用一个内部函数,而这个内部函数又去,引用外部的对象,这个时候就会造成内存泄漏。即 ie 下的 js互相引用会造成内存泄漏。
<body> <div id="div1"></div> <script> window.onload = function(){ var oDiv = document.getElementById('div1'); oDiv.onclick = function(){ alert(oDiv.id); } //就是这个简单的程序可能会造成 ie 下的内存泄漏,如果内存泄漏的 //话,当你页面跳转的时候,变量不会释放,一直存在于内存中,使你 //的 cpu 在累加,大大降低了浏览器的性能,只有当你关闭浏览器的 //情况下才能释放内存。 } </script> </body>解决方法如下:
<body> <div id="div1"></div> <script type="text/javascript"> window.onload = function(){ var oDiv = document.getElementById('div1'); oDiv.onclick = function(){ alert(oDiv.id); } //解决方法: window.onunload = function(){ oDiv.onclick = null; } } </script> </body>第二种解决方案:
<body> <div id="div1"> </div> <script type="text/javascript"> window.onload = function(){ var oDiv = document.getElementById('div1'); //第二种解决方法:在外部建一个变量引用一下 var id = oDiv.id; oDiv.onclick = function(){ alert(oDiv.id); } //调用完之后还要把这个对象置空 oDiv = null; } </script> </body>