setTimeout 中函数的值

Value to a function inside a setTimeout

我正在尝试设置一个超时值,查看 this question 我发现任何形式的 setTimeout(function(), int); 都会 'skip' 计时器,我怎么会按照下面的代码执行此操作?

$(".addtimer div").click(function(){
  $(this).toggleClass("remove");
  setTimeout(hide(this),2000);
});
function hide(name) {
  $(name).remove();
}

输出

".addtimer div" disappears instantly

由此变化:

setTimeout(hide(this),2000); 

对此:

var self = this;
setTimeout(function() {
    hide(self);
},2000);

您正在立即调用该函数并将其 return 值传递给 setTimeout,而不是将函数引用传递给 setTimeout 以便稍后调用。请记住 (xx) 表示立即执行。所以 hide(this) 的意思是现在执行,而不是稍后执行。另一方面,function() { hide(this); } 是一个可以稍后调用的函数引用。


或者,如果您没有在其他任何地方使用隐藏功能,那么您可以像这样集成它:

$(".addtimer div").click(function(){
    $(this).toggleClass("remove");
    var self = this;
    setTimeout(function() {
         $(self).remove();
    },2000);
});

一个有用的语言特性是 .bind(),它可用于 "hardwire" this 的值或回调函数的参数。例如,您可以这样做:

$(".addtimer div").click(function(){
    $(this).toggleClass("remove");
    setTimeout(function() {
         $(this).remove();
    }.bind(this),2000);
});

.bind(this)设置this的当前值为回调函数调用时this的值

或者,如果您仍然有函数 hide(item),那么您可以使用 .bind 将参数设置为 hide(),如下所示:

$(".addtimer div").click(function(){
    $(this).toggleClass("remove");
    setTimeout(hide.bind(null, this)), 2000);
});

或者,您可以使用动画并让它为您提供时间:

$(".addtimer div").click(function(){
    $(this).toggleClass("remove").delay(1000).slideUp(1000, function() {
        $(this).remove();
    });
});

如您所见,有很多选项,使用哪个在一定程度上取决于具体情况、您认为在您的情况下最清晰的代码以及您最习惯使用的内容。

第一个问题是您需要将一个函数传递给 setTimeout(您没有;您正在调用该函数并将其 return 值传递给 setTimeout),并且第二个是你需要正确处理this

获得 this 处理权的主要方法有两种。

.bind():

$(".addtimer div").click(function(){
    $(this).toggleClass("remove");

    // you could also use   function () { hide(this); }.bind(this)
    setTimeout(hide.bind(null, this), 2000);
});
function hide(name) {
    $(name).remove();
}

或使用别名变量:

$(".addtimer div").click(function(){
    $(this).toggleClass("remove");
    var self = this; 
    setTimeout(function () { hide(self) }, 2000);
});
function hide(name) {
    $(name).remove();
}

另一种选择是完全不使用 this 并使用 e.target(因为这是一个 jQuery DOM 事件处理程序):

$(".addtimer div").click(function (e){
    $(e.target).toggleClass("remove");
    setTimeout(function () { hide(e.target) }, 2000);
});
function hide(name) {
    $(name).remove();
}

正如我提到的 jQuery 的 .proxy,我认为最好举个例子。

function hide(name) {
    $(name).remove();
}

$('.addtimer div').click(function () {
    $(this).toggleClass('remove');
    setTimeout($.proxy(function () {
        hide(this);
    }, this), 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="addtimer">
    <div>Hello</div>
</div>

与原生 bind

function hide(name) {
    $(name).remove();
}

$('.addtimer div').click(function () {
    $(this).toggleClass('remove');
    setTimeout(function () {
        hide(this);
    }.bind(this), 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="addtimer">
    <div>Hello</div>
</div>

还有 closure.

function hide(name) {
    $(name).remove();
}

$('.addtimer div').click(function () {
    $(this).toggleClass('remove');
    setTimeout((function (element) {
        return function () {
            hide(element);
        };
    }(this)), 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="addtimer">
    <div>Hello</div>
</div>

当然,如果您删除 this 并使用回调的事件参数,那么 none 是必需的。

function hide(name) {
    $(name).remove();
}

$('.addtimer div').click(function (e) {
    $(e.target).toggleClass('remove');
    setTimeout(function () {
        hide(e.target);
    }, 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="addtimer">
    <div>Hello</div>
</div>

而在现代 ECMA5 中

function hide(name) {
    name.parentNode.removeChild(name);
}

[].forEach.call(document.querySelectorAll('.addtimer div'), function (item) {
    item.addEventListener('click', function (e) {
        e.target.classList.toggle('remove');
        setTimeout(function () {
            hide(e.target);
        }, 2000);
    }, false);
});
<div class="addtimer">
    <div>Hello</div>
</div>