2009-01-29 56 views
1

我在我的頁面上有一個多個菜單,它們全部使用相同的鼠標懸停和點擊事件,因此我決定將它變成一個函數。然而,變量似乎總是被分配給懸停(函數,函數)函數的最後一個參數。jQuery和關閉

$(document).ready(function() { 
menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
    } 
} 
menuMouseOver({ parent: '#menu1', 
       active: 'menu1_active', 
       childSelect: ':gt(0)'}, 
      { parent: '#menu2', 
       active: 'menu2_active', 
       childSelect: ':gt(0)'}); 
}); 

爲什麼是最後的console.log將始終記錄最後活躍而不是屬於參數[I]。活躍的一個。 (在這個例子中,它始終記錄下有效的的參數[1] .active) 我在做什麼錯了?

此外,真正的功能更復雜,但問題也出現在這個變體中。

回答

1

您的問題是懸停事件發生在執行方法的範圍之外。因此,在懸停執行時,您的活動變量已經通過了整個集合並停留在最後一個元素的活動狀態。所以你看到了這個問題,因爲最後一個日誌是一個事件,它超出了範圍,另外兩個在循環範圍內。

試試這個:

 $(parent).children(childSelect) 
      .not('.'+active).each(function(i, e) { 
       console.log(active); 
       $(this).data("active", active); 
      }) 
      .hover(function() { 
       $(this).addClass($(this).data("active")); 
      }, function() { 
       $(this).removeClass($(this).data("active"))); 
      }); 

這將實際存儲的DOM元素內的「活動」值,以便它可以在範圍內進行訪問。

+0

非常感謝。 – 2009-01-29 18:26:00

0

我絞盡腦汁,因爲它是一個奇怪的問題,但我重構功能了一下,可能是有用的(呵呵,有人要聰明得多與此同時回答):

$("#menu1,#menu2").each(function(){ 
    var id = $(this).attr("id"); 
    $(">li",this).not("."+id+"_active,:eq(0)").hover(function(){ 
     $(this).addClass(id+"_active"); 
    },function(){ 
     $(this).removeClass(id+"_active"); 
    }); 
}); 
4

JavaScript沒有塊範圍,所以你在for循環中聲明的那些變量在每次迭代時改變它們的值,並且所有這些函數都引用相同的變量。訣竅是在for循環中創建一個新的函數作用域,以便在迭代過程中聲明的變量被綁定。

您可以通過在循環中執行一個匿名函數實現這一點:

menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     (function(){ // anonymous function to create new scope 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
     })(); // execute the anonymous function 
    } 
} 

你以前有它的方式,大家的功能關閉了同一個變量的引用,所以用什麼都的最後一個值是,而不是功能創建時的價值。使用函數作用域將使其表現得如你所願。