前端开发必须知道的JS之闭包及应用

二. 闭包的应用 
  应用1: 
  这个是我在用js模拟排序算法过程遇到的问题。我要输出每一次插入排序后的数组,如果在循环中写成 
  setTimeout(function() { $("proc").innerHTML += arr + "<br/>"; }, i * 500); 
会发现每次输出的都是最终排好序的数组,因为arr数组不会为你保留每次排序的状态值。为了保存会不断发生变化的数组值,我们用外面包裹一层函数来实现闭包,用闭包存储这个动态数据。下面用了2种方式实现闭包,一种是用参数存储数组的值,一种是用临时变量存储,后者必须要深拷贝。所有要通过闭包存储非持久型变量,均可以用临时变量或参数两种方式实现。 

<!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> 
<title></title> 
<script type="text/javascript"><!-- 
var arr = [4, 5, 6, 8, 7, 9, 3, 2, 1, 0]; 
var $ = function(id) { return document.getElementById(id); } 
var Sort = { 
Insert: function() { 
for (var i = 1; i < arr.length; i++) { 
for (var j = 0; j < i; j++) { 
if (arr[i] < arr[j]) { 
arr[i] = [arr[j], arr[j] = arr[i]][0]; 
} 
} 
setTimeout((function() { 
var m = []; 
for (var j = 0; j < arr.length; j++) { 
m[j] = arr[j]; 
} 
return function() { 
$("proc").innerHTML += m + "<br>"; 
} 
})(), i * 500); 
//or 写成下面这样也可以 
/* 
setTimeout((function(m) { 
return function() { 
$("proc").innerHTML += m + "<br>"; 
} 
})(arr.join(",")), i * 500); 
*/ 
} 
return arr; 
} 
} 
// --></script> 
</head> 
<body> 
<div> 
var a = [4, 5, 6, 8, 7, 9, 3, 2, 1, 0];</div> 
<div> 
<input type="button" value="插入排序" onclick="Sort.Insert();" /> 
</div> 
Proc:
 
<div id="proc"> 
</div> 
</body> 
</html> 

应用2: 
  这个是无忧上的例子(点击这里查看原帖),为每个<li>结点绑定click事件弹出循环的索引值。起初写成 
id.onclick = function(){ alert(i); }  id.onclick = function(){alert(i);} 
发现最终弹出的都是4,而不是想要的 1、2、3,因为循环完毕后i值变成了4。为了保存i的值,同样我们用闭包实现: 

 
<!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> 
<title></title> 
<script type="text/javascript"><!-- 
window.onload = function() { 
for (var i = 1; i < 4; i++) { 
var id = document.getElementById("a" + i); 
id.onclick = (function(i) { 
return function() { 
alert(i); 
} 
})(i); 
} 
} 
// --></script> 
</head> 
<body> 
<ul> 
<li id="a1">aa</li> 
<li id="a2">aa</li> 
<li id="a3">aa</li> 
</ul> 
</body> 
</html> 

应用4: 
  这个是无忧上月MM的例子(点击这里查看原帖),用闭包实现程序的暂停执行功能,还蛮创意的。

 
<input type="button" value="继续" onclick='st();'/> 
<script type="text/javascript"><!-- 
var st = (function() { 
alert(1); 
alert(2); 
return function() { 
alert(3); 
alert(4); 
} 
})(); 
// --></script> 

把这个作用延伸下,我想到了用他来实现window.confirm。 

 
<!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> 
<title></title> 
<script type="text/javascript"> 
var $ = function(id) { return "string" == typeof id ? document.getElementById(id) : id; } 
var doConfirm = function(divId) { 
$(divId).style.display = ""; 
function closeDiv() { 
$(divId).style.display = "none"; 
} 
return function(isOk) { 
if (isOk) { 
alert("Do deleting..."); 
} 
closeDiv(); 
} 
} 
</script> 
<style type="text/css"> 
body 
{ 
font-family: Arial; 
font-size: 13px; 
background-color: #FFFFFF; 
} 
#confirmDiv 
{ 
width: 200px; 
height: 100px; 
border: dashed 1px black; 
position: absolute; 
left: 200px; 
top: 150px; 
} 
</style> 
</head> 
<body> 
<div> 
<input name="btn2" type="button" value="删除" onclick="doConfirm('confirmDiv');" /> 
<div id="confirmDiv" style="display: none;"> 
<div style='position: absolute; left: 50px; top: 15px;'> 
<p> 
你确定要删除吗?</p> 
<input type="button" value="确定" onclick="doConfirm('confirmDiv')(true);" /> 
<input type="button" value="取消" onclick="doConfirm('confirmDiv')(false);" /> 
</div> 
</div> 
</div> 
</body> 
</html> 

看了上面的这些应用,再回到前面的一句话:在动态执行环境中,数据实时地发生变化,为了保持这些非持久型变量的值,我们用闭包这种载体来存储这些动态数据。这就是闭包的作用。也就说遇到需要存储动态变化的数据或将被回收的数据时,我们可以通过外面再包裹一层函数形成闭包来解决。 
  当然,闭包会导致很多外部函数的调用对象不能释放,滥用闭包会使得内存泄露,所以在频繁生成闭包的情景下我们要估计下他带来的副作用。 
  毕了。希望能对大家有所帮助。 
者:JayChow 
出处:http://ljchow.cnblogs.com

原文地址:https://www.cnblogs.com/hellowzd/p/5155970.html