zoukankan      html  css  js  c++  java
  • 在JavaScript中怎样利用闭包

    JavaScript的变量作用域是通过函数来维护的。举个例子,对于函数:

    function add(a,b){
    return a+b;
    }
    而言,当使用不同的参数(不带参数的函数同样如此)调用它时:

    var sum1 = add(1,2);
    var sum2 = add(3,4);

    每次调用都会通过创建一个新的调用对象维护一个新的函数作用域,从而保证了sum1和sum2分别取得相应的 值3和7。

    而闭包的原理,也是如此。下面举两个例子,一个是因为闭包导致了问题,而另一个则利用闭包巧妙地通过函数的作用域绑定参数。这两个例子相关的HTML标记片断如下:

    <a href=”#” id=”closureExample”>利用闭包的例子(0.5秒后您会看到提示)</a>
    <a href=”#” id=”closureExample2″>由于闭包导致问题的例子1</a>
    <a href=”#” id=”closureExample3″>由于闭包导致问题的例子2</a>
    <a href=”#” id=”closureExample4″>由于闭包导致问题的例子3</a>


    例一:因遭遇闭包而导致问题

    上面标记片断中有4个<a>元素,假设要给后三个指定事件处理程序,使它们在用户单击时报告自己在页面中的顺序,比如:当用户单击第2个链接时,报告“您单击的是第2个链接”。

    为此,如果编写下列为后三个链接添加事件处理程序的函数:

    function badExample() {
      for (var i=2 ; i<=4 ; i++ ) {
        var el = document.getElementById(’closureExample’ + i);
        el.onclick = function(){
          alert(’您单击的是第’ + i + ‘个链接’);
        }
      }
    }
    然后,在页面载入完成后(不然可能会报错)调用该函数:

    window.onload = function(){
      badExample();
    }
    此时单击后3个链接,会看到警告框中显示什么信息呢?——全都是“您单击的是第5个链接”。为什么?

    因为在badExample()函数中指定给el.onclick的事件处理程序——也就是那个匿名函数是在badExample()函数运行完成后(用户单击链接时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但没有定义。然后,又到外部作用域,即badExample()函数中查找,此时有定义,但i的值是5(只有i大于5才会停止执行for循环)。因此,就会取得该值——这正是闭包(匿名函数)要使用其外部函数(badExample)作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。这个例子的问题怎么解决呢?大家自己想一想。

    例二:利用闭包绑定参数

    还是上面的HTML片段,我们要在用户单击第一个链接时延时弹出一个警告框——注意延时——怎么实现?答案是使用setTimeout()函数,这个函数会在指定的毫秒数之后调用一个函数,如:

    setTimeout(someFunc,500);
    但问题是,无法给其中的someFunc函数传递参数。而使用闭包则可以轻松解决这个问题:

    function goodExample(i) {
    return function(){alert(i);};
    }
    函数goodExample用来返回一个匿名函数(闭包)。而我们可以通过为它传递参数来使返回的匿名函数绑定该参数,如:

    var good = goodExample(’这个参数是通过闭包绑定的’);
    而此时,就可以将绑定了参数的good函数传递给setTimeout()实现延时警告了:

    setTimeout(good,500) //此时good中已经绑定了参数
    最后,与为第一个链接指定事件处理程序结合起来,完整的代码就是:

    window.onload = function(){
    var el = document.getElementById(’closureExample’);
    if (el){
        var good = goodExample(’这个参数是由闭包绑定的’);
        el.onclick = function(){
            setTimeout(good,500);
        }
    }
  • 相关阅读:
    asp.net文件上传
    给图片添加水印效果图的函数(可以在图片上添加自己的版权和LOGO图片的水印)
    DataGrid实现tooltip功能
    DataList编辑、更新、取消、删除、分页(分页控件AspNetPager.dll)
    SQL Server 中千分位格式化输出[转载]
    利用ASP.NET的三种缓存提高站点性能
    带Checkbox的TreeView(一) 完美兼容IE、Firefox ,在js中添加了getCurrentNode(evt)方法,注册方法变为TreeView1.Attributes.Add("onclick", "CheckEvent
    带checkbox的TreeView(二)
    经典blog
    六类UML图
  • 原文地址:https://www.cnblogs.com/top5/p/1862731.html
Copyright © 2011-2022 走看看