jQuery 方法链 & var 意料之外

jQuery method chaining & var meaning unexpected

1) 代码看似简单,但方法链接不起作用:

$('.button').on('click', function(){
$(this).removeClass('shadow').delay(500).addClass('shadow');
 });

2) 这个也不行:

$('.button').on('click' ,function() {
   setTimeout(function() {
    $(this).removeClass('shadow').addClass('shadow');
  }, 500);
});

3) 但这个确实如此!

$('.button').on('click' ,function() {
   var shadow = $(this).removeClass('shadow');
   setTimeout(function() {
   shadow.addClass('shadow');
   }, 500);
   });

请教有经验的码友: 1怎么了? 2 中已过时的 3 中的 var 执行了什么样的附加操作?这个案例颠覆了我对 var 的理解,因为我认为 var 只是某种数据持有者。

  1. 您的第一个片段不起作用,因为 .delay() 可用于延迟动画队列而不是其他人,即此处的 addClass

  2. 第二个片段的问题是,在 setTimeout 中,this 将指向 window。所以从技术上讲,您是从 window 中删除 class,而不是从您想要的元素中删除。为了克服这个问题,你可以做两件不同的事情,

  3. 您的第三个代码段正在运行,因为您不小心在那里创建了一个 closure。因此,即使在执行了点击事件处理程序之后,您在 setTimeout 中使用的变量也会被保留。

对于这种情况更好的解决方案是,

setTimeout 外的 this 收集到 variable 中并在

内使用
$('.button').on('click' ,function() {
   var $this = this.removeClass('shadow');
   setTimeout(function() {
    $this.addClass('shadow');
  }, 500);
});

使用bind改变setTimeout,

的上下文
$('.button').on('click' ,function() {
   $(this).removeClass('shadow');
   setTimeout(function() {
    $(this).addClass('shadow');
  }.bind(this), 500);
});

或者最近的arrow function,你可以这样,

$('.button').on('click' ,function() {
   $(this).removeClass('shadow');
   setTimeout(() => {
    $(this).addClass('shadow');
   }, 500);
});

.delay(time) 当队列中有动画时使用。但在您的情况下,您是 adding/removing 一个 property/attribute 值。

因此,您需要使用 setTimeout() 的延迟,例如:

$('.button').on('click', function(){
   var $t = $(this);
   $t.removeClass('shadow');
   setTimeout(function(){ $t.addClass('shadow'); }, 500);
});
  1. 第一个问题是 adding/removing property/attribute 值未添加到队列中。
  2. 第二个问题是 setTimeout 中的匿名函数有自己的作用域,$(this) 不引用 $('.button').
  3. 第三个问题是您没有对 shadow 变量中元素的引用。如果您 var shadow = $(this); 检查下面,这很可能会起作用:

$('.button').on('click' ,function() {
   var shadow = $(this);
   shadow.removeClass('shadow');
   setTimeout(function() {
      shadow.addClass('shadow');
   }, 500);
});