<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml xml:lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/vnd.wap.wml; charset=utf-8"/>
<meta http-equiv="Cache-Control" content="no-cache"/></head>
<card title="Javascript 每日测试 - 第九期 - Gracecode.com">
<p>今天的题目“看起来”没有任何的悬念。</p>

<pre>请问点击第三个链接时弹出的值？

&lt;div id=&quot;demo&quot;&gt;
    &lt;a href=&quot;#&quot;&gt;A&lt;/a&gt;
    &lt;a href=&quot;#&quot;&gt;B&lt;/a&gt;
    &lt;a href=&quot;#&quot;&gt;C&lt;/a&gt;
    &lt;a href=&quot;#&quot;&gt;D&lt;/a&gt;
&lt;/div&gt;

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

addHandlers(document.getElementById('demo').getElementsByTagName('a'));</pre><p>“很不幸”的是，上述的这段代码没有按照原意实现，点击它们所有的链接都是为 400。这是因为“点击以后执行 i * 100 ，而这个 i 是循环结束以后的值，按照上面的循环后值为 4”。</p>

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

<pre>var addHandlers = function(nodes) {
    for (var i = 0; i &lt; nodes.length; ++i) {
        (function () {
         var j = i * 100;
            nodes[i].onclick = function(ev) {
                alert(j);
            }
        }) ();
    }
}</pre><p>“<a href="http://www.gracecode.com/Archive/Display/695" title="http://www.gracecode.com/Archive/Display/695">期前也讨论过</a>，只不过那时还没有了解闭包，详细”。类似的题目，在<a href="http://www.gracecode.com/Archive/Display/1406" title="http://www.gracecode.com/Archive/Display/1406">《精通 Javascript》</a>中 23 页（<a href="http://realazy.org/jspro/" title="http://realazy.org/jspro/">中文版</a>）有提及。</p>

<pre>var addHandlers = function(nodes) {
    for (var i = 0; i &lt; nodes.length; ++i) {
        nodes[i].onclick = function(idx) {
            return function(ev) {
                alert(idx * 100);
            }
        }(i);
    }
}</pre><p>“另，如果是使用 <a href="http://developer.yahoo.com/yui/event/" title="http://developer.yahoo.com/yui/event/">YUI</a> 的话，可能会更直观些”</p>

<pre>var addHandlers = function(nodes) {
    for (var i = 0; i &lt; nodes.length; ++i) {
        YAHOO.util.Event.on(nodes[i], 'click', function(ev, idx) {
            alert(idx * 100);
        }, i);
    }
}</pre><p>使用闭包的话，必须注意两点：其一，就是避免出现无谓的匿名函数；其二，就是注意内存溢出。下面有几条有关闭包的参考链接。</p>

<ul>
    <li><a href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html" title="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html">http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html</a></li>
    <li><a href="http://www.felixwoo.com/article.asp?id=294" title="http://www.felixwoo.com/article.asp?id=294">http://www.felixwoo.com/article.asp?id=294</a></li>
    <li><a href="http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html" title="http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html">http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html</a></li>
    <li><a href="http://www.jibbering.com/faq/faq_notes/closures.html" title="http://www.jibbering.com/faq/faq_notes/closures.html">http://www.jibbering.com/faq/faq_notes/closures.html</a></li>
    <li><a href="http://www.cristiandarie.ro/asp-ajax/JavaScriptClosureInheritance.html" title="http://www.cristiandarie.ro/asp-ajax/JavaScriptClosureInheritance.html">http://www.cristiandarie.ro/asp-ajax/JavaScriptClosureInheritance.html</a></li>
    <li><a href="http://realazy.org/lab/js/closure.html" title="http://realazy.org/lab/js/closure.html">http://realazy.org/lab/js/closure.html</a></li>
    <li><a href="http://www.ibm.com/developerworks/cn/web/wa-memleak/index.html" title="http://www.ibm.com/developerworks/cn/web/wa-memleak/index.html">http://www.ibm.com/developerworks/cn/web/wa-memleak/index.html</a></li>
</ul>


<p>
<a href="http://www.gracecode.com/wap/">Gracecode.com</a> |
<a href="http://www.gracecode.com/wap/d/2076 ">Permalink</a>(<a href="http://www.gracecode.com/Archive/Display/2076 ">xHTML</a>) |
<a href="http://www.gracecode.com/Trackback/Recieve/2076/e08ppk">Trackback</a> |
<a href="http://rss.gracecode.com">Rss</a>
</p>
</card>
</wml>