2010-04-22 75 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,...