浅谈js中的闭包

首先我们先来看一段代码:

代码如下:

<a href="javascript:void(0);">111</a>
<a href="javascript:void(0);">222</a>
<a href="javacsript:void(0);">333</a>
var a=document.getElementsByTagName("a");
  function b(){
    for(var i=0;i<a.length;i++){
    a[i].onclick=function(){
      alert(i);
    }  
  }
}

  按照我们设计的初衷,应该是点击一个a标签就相应的弹出该标签的序列号,即点击第一个a就弹出0,点击第二个就弹出1...但是事实是弹出的始终是a标签的个数,这是什么原因呢?这个问题困扰了我很久,查阅了许多网上的资料还有参考书籍,大多说的似是而非,相信也有许多同学对其中原因也不甚了解,就这个问题我谈谈自己的理解,如有不当之处,还请批评指正。

  就我个人的理解,上述函数未能达到目的的原因是,事件处理函数绑定了变量i,而该事件处理函数又赋值给了onclick,即是说只有在点击a标签的时候才会调用该函数,因此从逻辑上来说,在单纯的for循环里面function(){alert(i);}这段函数实际上是没有执行的,而当我们点击a标签的时候for循环早就已经执行完毕,此时i的值就是for循环执行完毕的终态值。通俗一点理解,就是这个i的值是属于b函数的,而我们需要的i的值是实时传递进事件处理函数中的值。那么有什么方法可以实现我们的设计初衷呢?聪明的同学可能已经猜到了,那就是使用闭包。

下面我们再来看一段代码:

代码如下:

var a=document.getElementsByTagName("a");
  function b(){
    for(var i=0;i<a.length;i++){
      a[i].onclick=function(j){
        return function(){
        alert(j);
      }
    }(i);
  }
}
b();

  执行以上代码可以发现,我们所要的功能已经实现,即点击任意a标签都会弹出该标签所在的序列号。对上述代码,相信许多同学都看过许多雷同的版本,但是为什么这样做就能实现我们需要的功能了呢,一下是个人的一点浅见,如有不当,还请不吝赐教。

  对上述代码的理解,其本质就是对变量i的理解。在这段代码中,函数执行到for循环处发现了一个立即调用函数,这个时候给这个立即调用函数传递实时的i变量值,函数立即调用完成,事件处理函数也就存储了实时的i变量值。

以上所述就是本文的全部内容了,希望对大家理解js闭包能够有所帮助。

(0)

相关推荐

  • javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数

  • JavaScript闭包 懂不懂由你反正我是懂了

    越来越觉得国内没有教书育人的氛围,为了弄懂JS的闭包,我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释,当我看到stackoverflow上这一篇解答,我脑中就出现了一句话:就是这货没跑了! 不才译文见下,见笑了. Peter Mortensen问: 就像老Albert所说的,"如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂."好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了. 你们会怎么把它解释给一个充满好奇

  • js bind 函数 使用闭包保存执行上下文

    复制代码 代码如下: window.name = "the window object" function scopeTest() { return this.name; } // calling the function in global scope: scopeTest() // -> "the window object" var foo = { name: "the foo object!", otherScopeTest: fu

  • javascript闭包的理解

    1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部变量,注意在函数内部定义变量时一定要使用var关键字,不带var关键字的变量为全局变量. javascript中每一段代码都有与之关联的作用域链,这个作用域链是一个对象列表或者链表,定义了这段代码"作用域"中的变量.顶层代码的作用域由全局变量组成:不包含嵌套的函数的作用域链有两个对象:一个是定义的函数参数和局部变量的对象,一个是全局变量对象:而嵌套函数的

  • 浅谈JS闭包中的循环绑定处理程序

    前几天工作中写前端js代码时,遇到了遍历元素给它添加单击事件.就是这个问题让我整整调了一个下午.最后还是下班回家,上网查资料才知道怎么解决的. (PS:之前也在<jQuery基础教程>第四版中看过讲循环绑定处理程序的内容,当时估计也没怎么用心看,所以没记起来.) 大神要是知道这类情况,可以关掉窗口,写这些主要是给像我一样的小白看的.谢谢! 先贴上错误的例子让大家看看.(例子里面用到jQuery,请导入jQuery库) 复制代码 代码如下: <!DOCTYPE html PUBLIC &q

  • js闭包实例汇总

    Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 复制代码 代码如下: <script type="text/javascript"> var n=100; function parent(){   alert(n); } parent();//100 </script> 如果在php里 复制代码 代码如下: <?php $n=100; function parent(){   echo $n; }

  • js的闭包的一个示例说明

    复制代码 代码如下: function outside() { var myVar = 1; return function (){ alert(myVar); } } var t = outside(); t(); js中 某个函数的内部函数在该函数执行结束后仍然可以访问这个函数中定义的变量,这称为闭包(Closure) 下面例子是给三个锚anchor1,anchor2,anchor3添加onclick事件,可以预期的效果是点击锚点显示相应的锚点ID,实际上却都是显示"My id is anc

  • Javascript闭包演示代码小结

    闭包演示 p {background:gold;} function init() { var pAry = document.getElementsByTagName("p"); for( var i=0; i 产品 0 产品 1 产品 2 产品 3 产品 4 [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 以上场景是初学者经常碰到的.即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索

  • 详解js闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量 使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量.全局变量在每个模块都可调用,这势必将是灾难性的. 所以

  • js实现拖拽 闭包函数详细介绍

    js拖拽 采用简单的闭包实现方式 复制代码 代码如下: /** * Created with JetBrains WebStorm. * User: lsj * Date: 12-11-24 * Time: 下午12:59 * To change this template use File | Settings | File Templates. */ var dragmanager=(function() { //标识移动元素z轴坐标 var index_z=1; //当前的拖拽元素 var

  • 用js闭包的方法实现多点标注冒泡示例

    这两天在做地图这块,一点点js代码,各种坑.第一次接触js,各种难,下面就这几天的研究做一些总结,求坑 在事件监听器中使用闭包 在执行事件监听器时,通常可取的做法是将私有数据和持久性数据附加到对象中.JavaScript 不支持"私有"实例数据,但是支持允许内部函数访问外部变量的闭包.在事件监听器中,闭包非常适用于访问通常不附加到发生事件的对象的变量. 以下示例在事件监听器中使用了函数闭包将加密讯息分配给一组标记.点击每个标记将会看到加密讯息的一部分,该讯息并不包含在标记本身内. 复制

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

    在前端开发必须知道的JS之原型和继承一文中说过下面写篇闭包,加之最近越来越发现需要加强我的闭包应用能力,所以此文不能再拖了.本文讲的是函数闭包,不涉及对象闭包(如用with实现).如果你觉得我说的有偏差,欢迎拍砖,欢迎指教.一. 闭包的理论 首先必须了解以下几个概念: 执行环境 每调用一个函数时(执行函数时),系统会为该函数创建一个封闭的局部的运行环境,即该函数的执行环境.函数总是在自己的执行环境中执行,如读写局部变量.函数参数.运行内部逻辑.创建执行环境的过程包含了创建函数的作用域,函数也是在

  • JavaScript中的作用域链和闭包

    作用域 全局作用域 局部作用域 作用域链 执行上下文 活动对象 闭包 闭包优化 JavaScript中出现了一个以前没学过的概念--闭包.何为闭包?从表面理解即封闭的包,与作用域有关.所以,说闭包以前先说说作用域. 作用域(scope) 通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突. 全局作用域(Global Scope) 在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情形拥有全局作

  • js闭包的用途详解

    我们来看看闭包的用途.事实上,通过使用闭包,我们可以做很多事情.比如模拟面向对象的代码风格:更优雅,更简洁的表达出代码:在某些方面提升代码的执行效率. 1 匿名自执行函数 我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这些变量:造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的). 除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一

随机推荐