2012-08-17 111 views
0

裏面我有越來越具有以下顯示的「名稱」值一個問題:的javascript傳遞變量的函數等

for (var name in array) { 
     var hoverIn = function() { 
        alert(name); 
     }; 

     var hoverOut = function() { 
     }; 

     thing.hover(hoverIn, hoverOut); 

    } 

我得到的是名字的最後一個值的警告窗口。很明顯,我做錯了什麼,我懷疑這是一個簡單的修復。誰能幫忙?

謝謝。

回答

7

它是封閉的問題,name,後該迭代是array中的最後一個name,以及當迭代發生時不會立即執行懸停回調,因此當懸停功能實際執行時,name將永遠是array中的最後一個。

您需要使用IEFE(立即執行的函數表達式):

for (var name in array) { 
     // pass in name to the anonymous function, and immediately 
     // executes it to retain name when the particular iteration happens 
     var hoverIn = (function(name) { 
      return function() { 
        alert(name); 
      } 
     })(name); // if you notice, the pattern is (function(name) {})(name) 
        // the first() creates an anonymous function, the (name) 
        // executes it, effectively passing name to the anon fn 

     var hoverOut = (function(name) { 
      // same pattern if you need to re-use name inside here, otherwise just 
      // function() { } should suffice 
     })(name); 

     thing.hover(hoverIn, hoverOut); 

    } 

爲了避免重複(function() { })()(老實說,這是越來越累看),你也可以,因爲@pimvdb指出,包裹在關閉整個身體:

for (var name in array) { 
     (function(name) { 
      var hoverIn = function() { 
       alert(name); 
      } 

      var hoverOut = function() { 
      } 

      thing.hover(hoverIn, hoverOut); 
     })(name); // closure of for loop body 

    } 
+0

你不應該把var傳遞給函數!你爲什麼要創建一個名字的副本? – Serjio 2012-08-17 09:47:19

+0

檢查此http://jsfiddle.net/yHSpg/並說我在我的答案錯誤在哪裏? – Serjio 2012-08-17 09:50:18

+0

作爲一個方面說明,也可以包裝整個'for'循環體。 – pimvdb 2012-08-17 09:51:00

-2

您應該創建封閉:

for (var name in array) { 
     var hoverIn = (function() { 
       return function() { 
        alert(name); 
       }; 
     }()); 

     var hoverOut = function() { 
     }; 

     thing.hover(hoverIn, hoverOut); 
    } 
+0

這不會解決任何問題:他已經有一個關於var名稱的封閉。閉包關閉變量,而不是值。這就是爲什麼它不起作用。 – 2012-08-17 09:46:19

+0

在這裏,'name'仍然是指'for'循環中的一個,所以它不會改變任何東西。 – pimvdb 2012-08-17 09:47:20

+0

@MennovandenHeuvel你不明白什麼封閉意味着=)檢查這個小提琴 - http://jsfiddle.net/yHSpg/。然後會意識到這是錯誤的! – Serjio 2012-08-17 09:48:56

0

添加一個變量的循環中

var thisName = name; 

,然後用它在你的函數

alert(thisName); 
0

你有兩種方法來處理這個問題。

要知道的第一件事是範圍只發生在函數級別,而不是在JavaScript的循環內。 如果您在外部來源的函數中設置了一個變量,並且不立即執行該變量,該變量將在您的循環過程中進行更改。

您可以通過關閉其它變量解決這個問題:

var names = ["john","paul","george","ringo"]; 
var store = {}; 

//this function receives the data as a parameter 
//so it will be a safe copy. 

function createFunc(name){ 
    //just return a function that will alert the name. 
    return function(){ 
     alert(name); 
    } 
} 
for (var i in names) { 

     var hoverIn = createFunc(names[i]); 

     store[names[i]]=hoverIn; 

} 
store["john"](); 

另一種方法是創建執行馬上 在循環中的匿名函數:

var names = ["john","paul","george","ringo"]; 
var store = {}; 

for (var i in names) { 
    //the function receives the i as a parameter 
    //and executes, so n is a safe copy of i 
    (function(n){ 

    var hoverIn = function(){ 
     alert(names[n]); 
    } 

    store[names[n]]=hoverIn; 

    })(i); 

} 
store["john"](); 

一切都是個問題與關閉有關。 查看維基百科獲取更多信息。