为什么这两个JavaScript不等同? [英] Why aren't these two bits of JavaScript equivalent?

查看:113
本文介绍了为什么这两个JavaScript不等同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

in jquery 1.4.2,ff 3.6.6:

in jquery 1.4.2, ff 3.6.6:

下面的代码生成了三个div,它们像你所期望的那样向firebug控制台写入消息。但是,如果你取消注释循环并注释掉3行手动执行它,它不工作 - 鼠标在任何divs导致three被写到控制台。

The following code produces three divs, which write messages to the firebug console as you would expect. However, if you uncomment out the loop and comment out the 3 lines doing it manually, it doesn't work - mousing over any of the divs results in "three" being written to the console.

为什么这两种方法彼此不同?在每一个中,您使用一个选择器来查找元素并向其中添加一个事件。

Why are these two methods any different than each other? In each one you use a selector to find the element and add an event to it.

<head>
<script type="text/javascript" src="/media/js/jquery.js"></script>
<script>

$( document ).ready( function() {

  $("#one").mouseenter(function(){console.log("one")})
  $("#two").mouseenter(function(){console.log("two")})
  $("#three").mouseenter(function(){console.log("three")})

  //  names=['one','two','three'];
  //  for (k in names){
  //    id=names[k]
  //    $("#"+id).mouseenter(function(){console.log(id)})
  //  }
})
</script>
</head>

<body>
  <span id="one">ONE</span>
  <p><span id="two">TWO</span></p>
  <p><span id="three">THREE</span></p>
</body>


推荐答案

您将拥有一个非常常见的关闭问题中for loop。

You would be having a very common closure problem in the for in loop.

封闭在一个闭包中的变量共享同一个单一环境,所以在 mouseenter 回调被调用,循环将运行它的过程,并且 id 变量将指向 names array。

Variables enclosed in a closure share the same single environment, so by the time the mouseenter callback is called, the loop will have run its course and the id variable will be left pointing to the value of the last element of the names array.

这可能是一个棘手的话题,如果你不熟悉闭包的工作原理。您可以查看以下文章进行简要介绍:

This can be quite a tricky topic, if you are not familiar with how closures work. You may want to check out the following article for a brief introduction:

  • Mozilla Dev Center: Working with Closures

你可以用更多的闭包,使用函数工厂来解决这个问题:

You could solve this with even more closures, using a function factory:

function makeMouseEnterCallback (id) {  
  return function() {  
    console.log(id);
  };  
}

// ...

var id, k,
    names = ['one','two','three'];

for (k = 0; k < names.length; k++) {
  id = names[k];
  $("#" + id).mouseenter(makeMouseEnterCallback(id));
}

您还可以内联上述函数工厂,如下所示:

You could also inline the above function factory as follows:

var id, k, 
    names = ['one','two','three'];

for (k = 0; k < names.length; k++) {
  id = names[k];
  $("#" + id).mouseenter((function (p_id) {  
    return function() {  
      console.log(p_id);
    };  
  })(id));
}

任何另一个解决方案可以是@dm在另一个答案建议,将每个迭代包含在自己的范围内:

Any yet another solution could be as @d.m suggested in another answer, enclosing each iteration in its own scope:

var k, 
    names = ['one','two','three'];

for (k = 0; k < names.length; k++) {
  (function() {
    var id = names[k];
    $("#" + id).mouseenter(function () { console.log(id) });
  })();
}

虽然与此问题无关,但通常建议避免使用 for in 循环以遍历数组的项目,如 @CMS 在下面的评论中指出(更多阅读)。此外,使用分号明确地终止您的语句也被认为是JavaScript中的良好做法。

Although not related to this problem, it is generally recommended to avoid using a for in loop to iterate over the items of an array, as @CMS pointed out in a comment below (Further reading). In addition, explicitly terminating your statements with a semicolon is also considered a good practice in JavaScript.

这篇关于为什么这两个JavaScript不等同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆