今天的题目「看起来」没有任何的悬念。

请问点击第三个链接时弹出的值?

<div id="demo">
    <a href="#">A</a>
    <a href="#">B</a>
    <a href="#">C</a>
    <a href="#">D</a>
</div>

<script type="text/javascript">
var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        nodes[i].onclick = function(ev) {
            alert(i * 100);
        }
    }
}

addHandlers(document.getElementById('demo').getElementsByTagName('a'));

「很不幸」的是,上述的这段代码没有按照原意实现,点击它们所有的链接都是为 400。这是因为「点击以后执行 i * 100 ,而这个 i 是循环结束以后的值,按照上面的循环后值为 4」。

如果按照期望的写法,也就是点击链接以后 alert 不同的值,可以用闭包。比如下面有几个解决方案

var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        (function () {
         var j = i * 100;
            nodes[i].onclick = function(ev) {
                alert(j);
            }
        }) ();
    }
}

期前也讨论过 ,只不过那时还没有了解闭包,详细」。类似的题目,在 《精通 Javascript》 中 23 页( 中文版 )有提及。

var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        nodes[i].onclick = function(idx) {
            return function(ev) {
                alert(idx * 100);
            }
        }(i);
    }
}

「另,如果是使用 YUI 的话,可能会更直观些」

var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        YAHOO.util.Event.on(nodes[i], 'click', function(ev, idx) {
            alert(idx * 100);
        }, i);
    }
}

使用闭包的话,必须注意两点:其一,就是避免出现无谓的匿名函数;其二,就是注意内存溢出。下面有几条有关闭包的参考链接。