闭包的应用场景三
-------------------------------------------
闭包的应用场景
1.使用闭包代替全局变量
2.函数外或在其他函数中访问某一函数内部的参数
3.在函数执行之前为要执行的函数提供具体参数
4.在函数执行之前为函数提供只有在函数执行或引用时才能知道的具体参数
5.为节点循环绑定click事件,在事件函数中使用当次循环的值或节点,而不是最后一次循环的值或节点
6.暂停执行
7.包装相关功能
5.为节点循环绑定click事件,在事件函数中使用当次循环的值或节点,而不是最后一次循环的值或节点
//假设有两个a链接,id分别为"hello"、"world"
function test(obj){
return function(){
alert(obj.id);
}
}
var nodes=document.getElementsByTagName("a");
for(var i=0;i<nodes.length;i++){
var node=nodes[i]
nodes[i].attachEvent("onclick", function(){alert(node.id)})//点击链接时,hello链接弹出world,world链接也弹出world;
//这是因为循环完毕后,node被赋值为world元素
//这不是我们预期的结果!!!
//正确写法一// 内部参数parm为任意指定的参数,如:(function(node){return function(){alert(node.id)}})(node)
nodes[i].attachEvent("onclick",(function(parm){return function(){alert(parm.id)}})(node))
//第一次循环创建了一个闭包,缓存的node参数为hello链接。
//第二次循环又创建了一个闭包,缓存的node参数为world链接。
//点击链接时,hello链接弹出hello,world链接弹出world,因为他们调用的是各自的node参数
//正确写法二
var func=test(node);
nodes[i].attachEvent("onclick",func)
}
6.暂停执行
出处参考:http://ljchow.cnblogs.com
这个可以做很多实用和有意思的交互。
这个是无忧上月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。
<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>
7.包装相关功能
下面的代码定义了一个函数,这个函数用于返回一个 HTML 字符串,其中大部分内容都是常量,但这些常量字符序列中需要穿插一些可变的信息,而可变的信息由调用函数时传递的参数提供。
通过执行单行函数表达式返回一个内部函数,并将返回的函数赋给一个全局变量,因此这个函数也可以称为全局函数。而缓冲数组被定义为外部函数表达式的一个局部变量。它不会暴露在全局命名空间中,而且无论什么时候调用依赖它的函数都不需要重新创建这个数组。
如果一个函数依赖于另一(或多)个其他函数,而这些其他函数又没有必要被其他代码直接调用,那么可以运用相同的技术来包装这些函数,而通过一个公开暴露的函数来调用它们。这样,就将一个复杂的多函数处理过程封装成了一个具有移植性的代码单元。
/* 声明一个全局变量 - getImgInPositionedDivHtml -
并将一次调用一个外部函数表达式返回的内部函数赋给它。
这个内部函数会返回一个用于表示绝对定位的 DIV 元素
包围着一个 IMG 元素 的 HTML 字符串,这样一来,
所有可变的属性值都由调用该函数时的参数提供:
*/
var getImgInPositionedDivHtml = (function(){
/* 外部函数表达式的局部变量 - buffAr - 保存着缓冲数组。
这个数组只会被创建一次,生成的数组实例对内部函数而言永远是可用的
因此,可供每次调用这个内部函数时使用。
其中的空字符串用作数据占位符,相应的数据
将由内部函数插入到这个数组中:
*/
var buffAr = [
'<div id="',
'', //index 1, DIV ID 属性
'" style="position:absolute;top:',
'', //index 3, DIV 顶部位置
'px;left:',
'', //index 5, DIV 左端位置
'px;width:',
'', //index 7, DIV 宽度
'px;height:',
'', //index 9, DIV 高度
'px;overflow:hidden;\"><img src=\"',
'', //index 11, IMG URL
'\" width=\"',
'', //index 13, IMG 宽度
'\" height=\"',
'', //index 15, IMG 调蓄
'\" alt=\"',
'', //index 17, IMG alt 文本内容
'\"><\/div>'
];
/* 返回作为对函数表达式求值后结果的内部函数对象。
这个内部函数就是每次调用执行的函数
- getImgInPositionedDivHtml( ... ) -
*/
return (function(url, id, width, height, top, left, altText){
/* 将不同的参数插入到缓冲数组相应的位置:
*/
buffAr[1] = id;
buffAr[3] = top;
buffAr[5] = left;
buffAr[13] = (buffAr[7] = width);
buffAr[15] = (buffAr[9] = height);
buffAr[11] = url;
buffAr[17] = altText;
/* 返回通过使用空字符串(相当于将数组元素连接起来)
连接数组每个元素后形成的字符串:
*/
return buffAr.join('');
}); //:内部函数表达式结束。
})();
/*^^- :单行外部函数表达式。*///输出HTML字符串
document.write(getImgInPositionedDivHtml("www.baidu.com","hello",200,100,100,40,"hello"))