简体   繁体   English

在函数javascript中调用函数

[英]Calling a function inside a function javascript

I have this code inside the success function of a jQuery ajax call success: function(d) 我在jQuery ajax调用success: function(d)的成功函数中包含以下代码success: function(d)

for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        focusMarker(d.items[n].id);
    });
}

Unfortunately, the function always evaluated d.items[n].id as the last item in d.items collection. 不幸的是,该函数始终将d.items[n].id评估为d.items集合中的最后一项。

I tried making this modification: 我尝试进行此修改:

for (var n in d.items)
{        
    var id = d.items[n].id;        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        focusMarker(id);
    });
}

but my function always returned the same thing. 但是我的函数总是返回同一件事。

Is this a scope problem, or is there something wrong with my function definition? 这是一个范围问题,还是我的函数定义有问题?

There are several ways to solve this problem, the most common is to use a function to preserve the looping values: 有几种方法可以解决此问题,最常见的方法是使用一个函数来保存循环值:

for (var n in d.items) {
  (function(id) {
    google.maps.event.addListener(markers[id], 'mouseover', function() {
        focusMarker(id);
    });
  })(d.items[n].id);
}

By the way, if d.items is an array, I would recommend you to use a sequential loop eg: 顺便说一句,如果d.items是一个数组,我建议您使用顺序循环,例如:

for (var n = 0; n < d.items.length; n++) {
  //..
}

The for-in statement is meant to be used to enumerate over object properties. for-in语句旨在用于枚举对象属性。

If you use it on arrays or array like objects, it can give you several problems, first, inherited properties are also enumerated, meaning that if someone augments the Array.prototype object, those properties will be also enumerated in your loop. 如果在数组或类似对象的数组上使用它,可能会给您带来一些问题,首先,还会枚举继承的属性,这意味着如果有人扩充了Array.prototype对象,这些属性也会在循环中枚举。

Also the order of iteration is not guaranteed by the specification, the properties may not be visited in the numeric order. 同样,规范不能保证迭代的顺序,可能无法按数字顺序访问属性。

You can make a closure: 您可以关闭:

for (var n in d.items)
{        
    (function(id) {        
      google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
          focusMarker(id);
      });
    })(d.items[n].id)
}

This is a scope problem. 这是一个范围问题。 What you want to do is use a closure like this: 您想要做的是使用这样的闭包:

for (var n in d.items)
{        
    (function(id){
        google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
            focusMarker(id);
        });
    })(d.items[n].id);
}

Yes, it's a scope problem, and a very common one . 是的,这是一个范围问题,也是一个很常见的问题。

Variables enclosed in a closure share the same single environment, so by the time the mouseover callback is called, the for in loop will have run its course, and the n variable will be left pointing to the last value it was assigned. 闭包中包含的变量共享相同的单一环境,因此,在调用mouseover回调时, for in循环将运行,并且n变量将指向其最后分配的值。

You can solve this problem with even more closures, using a function factory: 您可以使用函数工厂使用更多的闭包来解决此问题:

function makeOnHoverHandler(id) {  
  return function () {  
    focusMarker(id);
  };  
}

// ...

for (var n in d.items) {        
  google.maps.event.addListener(markers[d.items[n].id], 
                                'mouseover', 
                                makeOnHoverHandler(d.items[n].id));
}

This can be quite a tricky topic, if you are not familiar with how closures work. 如果您不熟悉闭包的工作原理,那么这可能是一个棘手的话题。 You may want to check out the following Mozilla article for a brief introduction: 您可能需要查看以下Mozilla文章以进行简要介绍:

You could also inline the above. 您也可以内联以上代码。 This is actually a more common approach, but is practically the same as the above: 这实际上是一种更常见的方法,但实际上与上面的方法相同:

for (var n in d.items) {        
  google.maps.event.addListener(markers[d.items[n].id], 'mouseover', (function (id) {
    focusMarker(id);
  })(d.items[n].id));
}

Any yet another solution is to enclose each iteration in its own scope, by using self invoking anonymous functions: 还有另一种解决方案是通过使用自调用匿名函数将每个迭代包含在自己的范围内:

for (var n in d.items) {
  (function (id) {
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function () { 
      focusMarker(id);
    });
  })(d.items[n].id);
}

Similar to other responses, but I think defining things inline is neater, more concise style: 与其他响应类似,但我认为内联定义的内容更简洁,更简洁:

for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', new function() {
        return function() {
            focusMarker(d.items[n].id);
        }
    });
}

You might wonder what new function() does. 您可能想知道new function()作用。 That declares and executes a function all at once. 一次声明并执行一个函数。 It's basically shorthand for: 它基本上是:

for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        return function() {
            focusMarker(d.items[n].id);
        }
    }());
}

Although I think that second example may not work, because if you're not assigning the result to a variable you need extra parenthesis. 尽管我认为第二个示例可能不起作用,但是因为如果您不将结果分配给变量,则需要额外的括号。 For example: 例如:

function() { alert("hi"); }();

Is a syntax error. 是语法错误。 Has to be: 必须:

(function() { alert("hi"); })();

Does inline as a function argument count as assignment? 内联作为函数参数算作赋值吗? I don't know. 我不知道。 Better stick with my first example. 最好坚持我的第一个例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM