【问题标题】:JS variable scope missunderstandingJS 变量作用域误解
【发布时间】:2010-04-22 07:55:23
【问题描述】:

我有一个小问题: 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 什么是逻辑,因为当函数单击触发时 i 实际上是 5。但我希望 i 与我的 &lt;a&gt; 标记中的 i 相同。处理这个问题的最佳方法是什么?

例如,我可以将 i 放入 &lt;a&gt; 标记的 data() 中,但我确信有更简单的方法。

【问题讨论】:

标签: javascript


【解决方案1】:
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');
});

【讨论】:

  • (function(){...})() 充当词法包装器(或“范围”),将icurrent 值作为参数。内部(返回)函数在技术上是一个闭包,可以看到捕获的i
【解决方案2】:

你可以使用一个额外的函数来返回你的函数:

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');
}

使用这个附加函数,alert 中的内部 i 引用该函数的参数 i,而不是外部作用域的 i

【讨论】:

    【解决方案3】:

    你需要创建一个新的作用域,否则每个函数都会引用同一个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】:

      在您的代码示例中,i 基本上是一个全局变量。到 alert() 代码执行时,i 具有 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】:

        你可以使用绑定函数的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');
        }
        

        【讨论】:

        • 就像我在问题中所说的那样,我正在寻找无需使用 data() 的解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-11
        • 2017-12-24
        相关资源
        最近更新 更多