码迷,mamicode.com
首页 > 其他好文 > 详细

循环中的闭包

时间:2014-08-29 18:13:48      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   java   io   strong   

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

 

 

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

有如下代码:

<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);
        }
    }
}

 

循环中的闭包

标签:style   blog   http   color   os   使用   java   io   strong   

原文地址:http://www.cnblogs.com/zjzhome/p/3945319.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!