【问题标题】:Jquery Scope IssueJquery范围问题
【发布时间】:2011-03-11 00:59:40
【问题描述】:

我无法弄清楚这个范围问题:

var menuLinks = new Array("about.php", "contact.php");
function setClickListeners()
{
    for(var i=0; i<menuItems.length; i++)
    {
        $("#" + menuItems[i]).click( function () {
            window.alert(menuLinks[i]);
        });
    }
}

注意事项:menuItems 和 menuLink 的长度是一样的。此代码已被精简,以便于理解。

单击项目时此代码的结果是警报“未定义”。应该是 menuLinks 中的数据。

帮助!!!!

弗兰基

【问题讨论】:

  • 封闭范围陷阱!闭包会像这样进入 for 循环。你需要一个let
  • 添加menuItems 的代码可能会使您的帖子更加清晰。

标签: javascript jquery scope


【解决方案1】:
for (var i=0; i < menuItems.length; i++) {
    (function(i) {
         $("#"+menuItems[i]).click(function() {
              alert(menuLinks[i]);
         });
    }(i));
}

您需要将i当前 值设置为.click 中的匿名函数的本地值。

JavaScript 仅具有函数作用域。因此,如果您不将 i 设为本地,那么每当您按下点击时,i 的值就是 当前 值,在这种情况下为 menuItems.length - 1

您在上面所做的是创建一个新的函数范围并将i 的值传递给它,以便i 的当前值在该函数范围内保持不变。这样,您的 click 函数会从闭包中获取 i 的常量值。

jslint

让我们把代码复杂化并满足 jslint。

var wrapper = function(i) {
    $("#"+menuItems[i]).click(function() {
         alert(menuLinks[i]);
    });
};

for (var i=0; i < menuItems.length; i++) {
    wrapper(i);
}

【讨论】:

  • jsLint 会抱怨在循环中创建函数。
  • @david 使用 jshint 代替。它不会发牢骚。
  • -1 或只是嫉妒/怨恨的任何实际原因?
  • 第二个版本,使用预定义函数效率更高。在循环中重新定义和调用匿名函数很聪明,但不是最优的。如果预定义函数被称为比包装器更具描述性的东西,比如addMenuAction,代码也会更加自我解释。为什么需要闭包的解释非常清楚,所以+1
  • @meduw 这是针对任何微不足道的小循环的微优化。微优化是邪恶的。它是否提供更高的可读性是有争议的。
【解决方案2】:

更简洁的代码:

var menuLinks = new Array("about.php", "contact.php");
function setClickListeners()
{
    $.each(menuLinks, function(i, element)
    {
        $("#" + menuItems[i]).click( function (e) {
            alert(menuItems[i]);
            e.preventDefault();
        });
    }
}

【讨论】:

  • 除了 menuLinks 和 menuItems 不同 ;) 这没有任何作用。
  • 对不起,我的错误...试试这个!请记住,必须在循环中声明 menuItems。
猜你喜欢
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多