代码之家  ›  专栏  ›  技术社区  ›  meo

JS变量范围理解错误

  •  0
  • meo  · 技术社区  · 14 年前

    我有一个小问题: slidehelpers.total=4个

    for (i=1;i <= slideHelpers.total; i++) {
        $('<a href="#">' + i + '</a>').bind('click', function(){ alert('go to the ' + i + ' slide')}).appendTo('.slideaccess')
    }
    

    警报给出5什么是逻辑,因为当函数单击触发器时,我实际上是5。但是我想和我的一样 <a> 标签。最好的方法是什么?

    我可以把我放在 <A & GT; 例如,标记,但我确信有一种更简单的方法。

    5 回复  |  直到 14 年前
        1
  •  2
  •   James    14 年前
    for (i=1;i <= slideHelpers.total; i++) {
        $('<a href="#">' + i + '</a>').bind('click',
            (function(i){
                // Capture i in closure
                return function(){
                    alert('go to the ' + i + ' slide')
                };
            })(i)
        ).appendTo('.slideaccess')
    }
    

    优化:

    var ary = [], i = 0, n = slideHelpers.total,
        open = '<a class="index" href="#">',
        close = '</a>';
    
    // Fill array with numbers: 1,2,3,4,5...
    while (++i < n) ary[i] = i + 1;
    
    $('.slideaccess').append(
        open + ary.join(close + open) + close
    ).delegate('a.index', 'click', function() {
        var index = $.text(this);
        alert('go to the ' + index  + ' slide');
    });
    
        2
  •  2
  •   Gumbo    14 年前

    您可以使用返回函数的附加函数:

    for (i=1;i <= slideHelpers.total; i++) {
        $('<a href="#">' + i + '</a>').bind('click',
            (function(i) {
                return function() {
                    alert('go to the ' + i + ' slide');
                };
             })(i)
         ).appendTo('.slideaccess');
    }
    

    有了这个附加功能,内部 i 在你 alert 指的是论点 而不是对 外部范围。

        3
  •  1
  •   Quentin    14 年前

    您需要创建一个新的作用域,否则每个函数都将引用相同的 i . 在javascript中,变量的作用域是函数。

    var make_alert_message = function make_alert_message(num) {
        return function () { 
            alert('go to the ' + num + ' slide');
        };
    }
    
    for (var i = 1; i <= slideHelpers.total; i++) {
        $('<a href="#">' + i + '</a>').bind(
            'click', make_alert_message(i)
            ).appendTo('.slideaccess')
    }
    
        4
  •  1
  •   gnarf    14 年前

    在代码示例中 i 基本上是一个全局变量。到那时 alert() 代码执行, 具有for循环的最大值。在javascript中解决这个问题的标准方法是创建一个新的函数,它有自己的函数 scope “保持”变量。以返回事件处理函数的代码为例:

    (function(i) { // using i as an argument here 'scopes' it
       var something = i; // also within this function scope.
       // inside here, both i and something will only ever reference the "local scope"
    
       return function() {
         alert(i);
       };
    })(i); // and here we are calling that function with i = 1,2,3,...
    
        5
  •  0
  •   Darin Dimitrov    14 年前

    你可以用 eventData 绑定函数的:

    for (var i = 1; i <= slideHelpers.total; i++) {
        $('<a href="#">' + i + '</a>').bind('click', { index: i }, function(arg) { 
            alert('go to the ' + arg.data.index + ' slide');
        }).appendTo('.slideaccess');
    }