• 前端开发必须知道的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

  • 相关阅读:
    PostGIS解压版安装
    gulp监听文件变化,并拷贝到指定目录
    pre在火狐中不换行
    Undefined symbols for architecture i386: "_crc32", referenced from:
    响应式自动化开发流程-Windows 版
    Gulp入门教程
    SVG折线图
    git-版本控制
    log4j
    CSS:描述样式
  • 原文地址:https://www.cnblogs.com/hellowzd/p/5155970.html
Copyright © 2020-2023  润新知