2012-08-17 116 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"](); 

一切都是个问题与关闭有关。 查看维基百科获取更多信息。