2010-04-22 79 views
0

我有一个小问题: slideHelpers.total = 4JS变量的作用域missunderstanding

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>标签具有相同的i。处理这个问题的最好方法是什么?

我可以把我在<a>标签的数据(),但我相信有一个更简单的方法。

+1

欢迎来到今天的关闭循环问题问题!见例如。 http://stackoverflow.com/questions/2568966/how-do-i-pass-the-value-not-the-reference-of-a-js-variable-to-a-function和更多的背景。 – bobince 2010-04-22 08:42:44

回答

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

感谢它的作品,你能解释一下你的例子吗? – meo 2010-04-22 08:02:07

+1

'(function(){...})()'作为一个词法包装器(或“范围”),它被赋予**当前**值作为参数。内部(返回)函数在技术上是一个闭包,可以看到捕获的'i'。 – James 2010-04-22 08:05:07

0

您可以使用绑定功能的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'); 
} 
+0

像我告诉我的问题,我正在寻找一个解决方案,而不必使用数据()。 – meo 2010-04-22 08:09:11

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

1

您需要创建一个新的范围,否则每个函数都会引用相同的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') 
} 
1

在你的代码示例中,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,...