那个= $(this)的setTimeout闭包没有按预期工作

时间:2016-08-15 02:27:53

标签: javascript jquery closures

我想在按钮setTimeout中使用mouseout,并从$(this)引用setTimeout(按钮)。我正在使用that = $(this),然后在that中使用setTimeout,但它并不像预期的那样有效。

如果你慢慢地将鼠标悬停在每个链接上,它就能正常工作(1,2,3)。但是如果你在100毫秒以下快速完成,我得到全部3s(3,3,3)。

我的猜测是关闭不起作用而that var被覆盖但我无法弄清楚原因。

你能解释一下发生了什么吗?



$("nav a")
  .mouseenter(function() {
    //
  })
  .mouseout(function(event) {
  	that = $(this);
  	setTimeout(function(){
        		console.log( that.data('uid') );
        }, 100);
  });

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
  <ul>
    <li><a href="" data-uid="1">One</a></li>
    <li><a href="" data-uid="2">Two</a></li>
    <li><a href="" data-uid="3">Three</a></li>
  </ul>
</nav>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:3)

您应该将that设置为本地变量(使用var):

$("nav a")
  .mouseenter(function() {
    //
  })
  .mouseout(function(event) {
  	var that = $(this);
  	setTimeout(function(){
        		console.log( that.data('uid') );
        }, 100);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
  <ul>
    <li><a href="" data-uid="1">One</a></li>
    <li><a href="" data-uid="2">Two</a></li>
    <li><a href="" data-uid="3">Three</a></li>
  </ul>
</nav>

在您当前的代码中,that是一个全局变量,并且每个mouseout都会将其覆盖为新元素。

答案 1 :(得分:2)

您的变量将被提升到没有var关键字的全局变量。您应该考虑在将来使用strict mode来避免这种情况。

编辑:正如@Dekel在评论中指出的那样,严格模式实际上不会解决您的问题,但是当您尝试声明没有var关键字的变量时会出错。帮助避免这种意外行为只是一种很好的做法。

'use strict';

$("nav a")
  .mouseenter(function() {
    //
  })
  .mouseout(function(event) {
  	var that = $(this);
  	setTimeout(function(){
        		console.log( that.data('uid') );
        }, 100);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
  <ul>
    <li><a href="" data-uid="1">One</a></li>
    <li><a href="" data-uid="2">Two</a></li>
    <li><a href="" data-uid="3">Three</a></li>
  </ul>
</nav>