循环中的闭包

闭包这个概念,一直都不太懂,现在也是。。。

前几天参加了阿里前端的在线笔试,有这样一道题:

有如下代码:

<p>p1</p>
<p>p2</p>
<p>p3</p>
<p>p4</p>
<p>p5</p>

var ps = document.getElementsByTagName(‘p‘);
for(var i = 0; i < ps.length; i++) {
    ps[i].onclick = function() {
        alert(i);
    }
}

写出上述代码的运行结果,如果要输出 0 ~ length-1,如何修改代码,至少两种方法。

开始不知道在考什么,这两天在看书,才发现这样的问题其实是很常见的,泪奔~~

上面代码,依次单击,都会弹出5。

当 alert 被调用的时候,匿名函数保持对外部变量 i 的引用,此时for循环已经结束, i 的值被修改成了 5.

也就是说,每个p元素都绑定了单击事件,就是alert(i),但i的值在循环结束后已经变成5了,所以每一次单击都是弹出5。

那么如何一次弹出0,1,2,3,4,5呢,就需要每一次循环的时候把当前的i拷贝出来。

方法1就是使用立即执行函数:

for(var i = 0; i < ps.length; i++) {
    (function(e) {
        ps[i].onclick = function() {
            alert(e);
        }
    })(i);
}

外部的匿名函数会立即执行,并把 i 作为它的参数,此时函数内 e 变量就拥有了 i 的一个拷贝。

当传递给 单击的匿名函数执行时,它就拥有了对 e 的引用,而这个值是不会被循环改变的。

方法二是从匿名函数中返回一个函数:

for(var i = 0; i < ps.length; i++) {
    ps[i].onclick = (function(e) {
        return function() {
            alert(e);
        }
    })(i);
}

参考:http://bonsaiden.github.io/JavaScript-Garden/zh/#function.closures

http://javascript.ruanyifeng.com/grammar/function.html#toc18

其实自己也是似懂非懂,不过我倒是写出了下面的方法,不知道是不是正规军。。。

在外层套一个父div,然后在div上添加单击事件。

<div>
    <p>p1</p>
    <p>p2</p>
    <p>p3</p>
    <p>p4</p>
    <p>p5</p>
</div>

var div = document.getElementsByTagName(‘div‘)[0];
var ps = document.getElementsByTagName(‘p‘);

div.onclick = function(e) {
    for(var i = 0; i < ps.length; i++) {
        if(e.target == ps[i]) {
            alert(i);
        }
    }
}
时间: 2024-07-29 20:52:02

循环中的闭包的相关文章

循环中的闭包问题

循环中使用闭包,假设我们需要在每次循环中调用循环序号 for(var i = 0; i < 10; i++) {setTimeout(function() {console.log(i); }, 1000);}上面的代码不会输出数字 0 到 9,而是会输出数字 10 十次. 当 console.log 被调用的时候, 匿名函数保持对外部变量 i 的引用,此时 for循环已经结束, i 的值被修改成了 10. 为了得到想要的结果,需要在每次循环中创建变量 i 的 拷贝. 避免引用错误为了正确的获得

经典面试题,循环中使用闭包解决 var 定义函数的问题--闭包

闭包的定义很简单:函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包. <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>var定义函数出现的问题</title></head><body><script type="text/ja

彻底弄懂js循环中的闭包问题

第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下: 先看代码:demo.html<!DOCTYPE HTML> <html>  <head>   <meta charset="gbk"/>   <title>闭包循环问题</title>   <style type="text/css&quo

JavaScript中的闭包(Closure)

在上一篇介绍JavaScript this 关键字的文章中我们提到了闭包这个概念.闭包是指有权访问另一个函数作用域中的变量的函数.从函数对象中能够对外部变量进行访问(引用.更新),是构成闭包的条件之一.创建闭包的常见方式,就是在一个函数内部创建另一个函数.为了理解闭包,先来看一下什么是变量的生命周期. 变量的声明周期,就是变量的寿命,相对于表示程序中变量可见范围的作用域来说,生命周期这个概念指的是一个变量可以在多长的周期范围内存在并能够被访问.看下面一个例子: functionextent() 

JavaScript中的闭包

闭包: 在MDN中的解释:闭包是指那些能够访问独立(自由)变量的函数 (变量在本地使用,但定义在一个封闭的作用域中).换句话说,这些函数可以"记忆"它被创建时候的环境. 简单理解就是: 如果一个函数会在其父级函数返回之后留住对父级作用域的链接的话,相关闭包就会被创建出来. 闭包#1: var a = "global variable"; var F = function(){ var b = "local variable"; var N = f

Javascript中的闭包(转载)

前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到闭包以及在后面提到了一些闭包的高级用法.下面大家一起来学习Javascript中的闭包. 谈一谈JavaScript作用域链 当执行一段JavaScript代码(全局代码或函数)时,JavaScript引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加载后会

[译] Lua中的闭包

原文:(PDF) Lua中的闭包 摘要 第一类(first-class)函数是一种非常强大的语言结构,并且是函数式语言的基础特性.少数过程式语言由于其基于栈的实现,也支持第一类函数.本文讨论了Lua 5.x用于实现第一类函数的新算法.与之前所使用的技术不同,该算法不需要对源代码做静态分析(一种会极大降低Lua代码生成器即时性的技术)并且可支持使用顺序栈存储常规局部变量. 1 介绍 第一类函数是函数式语言的标志性特征,在过程式语言中也是很实用的概念.很多过程式函数如果以高阶函数的形式编写则会增加可

(转)深入理解JavaScript的闭包特性 如何给循环中的对象添加事件

深入理解JavaScript的闭包特性如何给循环中的对象添加事件 初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript的闭包特性. 有个网友问了个问题,如下的html,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4. 1.  <!DOCTYPE HTML> 2.  <html> 3.  <head&g

关于在for循环中绑定事件打印变量i是最后一次。

其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #box{ width:100px; height:100px; background-color:pink; } </style> <