that = $(this)表示setTimeout闭包没有按预期工作

that = $(this) for a setTimeout closure not working as expected

本文关键字:工作 闭包 setTimeout this 表示 that      更新时间:2023-09-26

我想在按钮mouseout中使用setTimeout,并参考setTimeout中的$(this)(按钮)。我使用that = $(this),然后在setTimeout中使用that,但它不像预期的那样工作。

如果你把鼠标悬停在每个链接上,它可以工作(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>

您应该将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,您都将其重写为新元素。

您的变量被提升为没有var关键字的全局变量。您应该考虑使用严格模式来避免将来出现这种情况。

编辑:正如@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>