闭包是指有权访问另一个函数作用域中的变量的函数。
这里随意写个最简单的小例子:
1 //这是闭包的一个基本例子 2 3 function outter( ){ 4 5 var temp = 0; //不加var则是全局变量! 6 7 function inner( ){ 8 9 return ++temp; //1、使用另一个(外部)函数变量 10 11 } 12 13 return inner; //2、返回对内部函数的引用 14 } 15 16 var test = outter()(); //3、调用函数 17 18 console.log(test);//输出:1
为神马可以取到函数的局部变量呢?
首先说说js的内存回收机制:函数执行时,其定义的变量会在内存空间中保存,等函数执行完毕,变量销毁内存释放。但是如果这个函数内部又嵌套了另一个函数呢?自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收.
下面说说需要注意的几种情况:
情况1:请看例子
1 /*这是http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html 的例子,本人太懒,借用下,嘿嘿~ 2 */ 3 var result=[]; 4 5 function foo(){ 6 var i= 0; 7 8 for (;i<3;i=i+1){ 9 //亮点来了,这里面的i,其实是外层循环i的引用 10 result[i]=function(){ 11 alert(i) 12 } 13 } 14 }; 15 16 foo(); 17 result[0](); // 3 18 result[1](); // 3 19 result[2](); // 3 20 21 //正确的写法如下 22 var result=[]; 23 24 function foo(){ 25 var i= 0; 26 for (;i<3;i=i+1){ 27 result[i]=(function(j){ 28 return function(){ 29 alert(j); 30 }; 31 })(i); 32 } 33 }; 34 35 foo(); 36 result[0](); // 0 37 result[1](); // 1 38 result[2](); // 2
同样的例子还有:
1 window.onload = function () 2 3 { 4 5 var oLi = document.getElementsByTagName("li"); 6 7 for (var i = 0; i < oLi.length; i++) 8 9 { 10 11 oLi[i].index = i; 12 13 oLi[i].onclick = function() { 14 15 console.log(oLi[i].index);//直接用i不行的哦~ 16 17 }; 18 19 } 20 21 }
情况二:
1 var name = "The Window"; 2 3 var object = { 4 name : "My Object", 5 6 getNameFunc : function(){ 7 8 var that = this; //匿名函数的this是全局变量,so... 9 10 return function(){ 11 12 return that.name;//这里如果用this.name 其实是The Window,现在则是我们期望的My Object 13 14 }; 15 } 16 };
情况三(也称内存泄露):
如果闭包的作用域链中包含一个HTML元素,则该元素无法被销毁,如:
function example(){ var ele = document.getElementById("someElement"); ele.onclick = function(){ console.log(ele.id);//无法释放 } };
改进代码如下:
1 function example(){ 2 var ele = document.getElementById('someELement'); 3 var id = ele.id; 4 5 ele.onclick = function(){ 6 console.log(id); 7 }; 8 9 ele = null; 10 };