【问题标题】:Javascript Array addEventListenerJavascript 数组 addEventListener
【发布时间】:2011-06-19 03:23:45
【问题描述】:

带有状态形状按钮的交互式地图,每个按钮都有状态缩写作为 id,当单击按钮/状态时,我想触发函数“stateSelect”并发送状态缩写,所以我知道什么被按下。为什么以下不起作用?

    var stateList = new Array("AK","AL","AR","AS","AZ","CA","CO","CT","DC","DE","FL","GA","GU","HI","IA","ID",
    "IL","IN","KS","KY","LA","MA","MD","ME","MH","MI","MN","MO","MS","MT","NC","ND","NE","NH","NJ","NM","NV","NY",
    "OH","OK","OR","PA","PR","PW","RI","SC","SD","TN","TX","UT","VA","VI","VT","WA","WI","WV","WY");

    for (var i = 0; i < stateList.length; i++) {
        document.getElementById(stateList[i]).addEventListener('mousedown', function() {stateSelect(stateList[i])}, false);
    }

我显然想避免 50 行代码,但我不确定为什么这个简单的循环不起作用。

【问题讨论】:

    标签: javascript arrays loops for-loop addeventlistener


    【解决方案1】:

    因为当处理程序运行时,它会查找i 的值,即循环结束后它所在的位置。

    您需要在函数中限定i 变量的范围:

    function listenerForI( i ) {
        document.getElementById(stateList[i]).addEventListener('mousedown', function() {stateSelect(stateList[i])}, false);
    }
    for (var i = 0; i < stateList.length; i++) {
        listenerForI( i );
    }
    

    现在处理程序引用的i 将成为被调用的listenerForI 函数的参数。因此,i 将引用从 for 循环传入的值。

    【讨论】:

    • 我试过上面的代码,现在只有阿拉斯加(AK)是可点击的。
    • 知道了,我以为我已经创建了用于操作的 div,但第一个块就成功了。非常非常感谢。
    【解决方案2】:

    您有范围界定问题。 Javascript 不是块范围的;它是功能范围的。基本上,当您希望在循环中创建新变量时,必须创建一个新函数。

    最优雅的方法如下:

    stateList.map(function(abbrev){
        $(abbrev).mousedown(function(){stateSelect(abbrev)});
    });
    

    如果您不使用 jQuery,只需将 $(abbrev).mousedown 替换为 document.getElementById(abbrev).addEventListener

    (只是为了抢占那些“地图不是标准”的人;它在 javascript ECMA-262 标准第 5 版中,得到了所有浏览器供应商的支持。如果有人对支持旧浏览器感到偏执,可以$.map.)

    这是使用for 循环的方法;它有点难看,但它证明了通过函数创建新闭包的必要性:

    for(var i=0; i<stateList.length; i++)
        (function(i){
            $(stateList[i]).mousedown(...);
        })(i);
    

    就像我说的,比必要的有点丑;你也可以这样做,它稍微不那么难看,但基本上是一样的:

    function createListener(abbrev) {
        $(abbrev).mousedown(...);
    }
    for(var i=0; i<stateList.length; i++)
        createListener(stateList[i]);
    

    【讨论】:

    • “如果有人偏执于支持旧版浏览器……” 这不是偏执。 IE6-8 不支持Array.prototype.map,这是一个巨大的基础。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 2017-11-02
    相关资源
    最近更新 更多