为什么我必须在匿名函数中包含Javascript函数调用才能立即调用它?

时间:2013-01-16 23:25:28

标签: javascript jquery closures anonymous-function

我有这个Javascript函数:

function Card(term, def, terms, curTerm) {
    this.term = term;
    this.def = def;
    this.terms = terms;
    this.curTerm = curTerm;

    this.show = function() {
        that = this;
        var html = createCard(that.term, that.def);
        $('body').append(html);
        $('input[type=text]').focus();
        $('.answer').on('click', function(event) {
            event.preventDefault();
            answer = $(this).parent().serializeArray()[0].value;

            // answer correct
            if (that.term === answer) {
                $('.card').addClass('correct');
                $('form').replaceWith('<h2>Correct! ' + that.term + '</h2>');
                setTimeout(function () {that.destroy(terms, curTerm + 1);}, 1500);

            // answer incorrect
            } else {
                $('.card').addClass('incorrect');
                $('form').replaceWith('<h2>Incorrect! ' + that.term + '</h2>');
                setTimeout(function () {that.destroy(terms, curTerm);}, 1500);
            }
        });
    };

我遇到的问题是setTimeout(function () {that.destroy(terms, curTerm + 1);}, 1500);。最初我有setTimeout(that.destroy(terms, curTerm + 1), 1500);,但它没有设置它刚刚调用that.destroy的超时。为什么在放入匿名函数时不立即调用它?这与封闭有什么关系吗?因为看起来我不得不创建一个闭包,但我还没有想出足够的知识来确定它们。

任何想法都会受到赞赏。

3 个答案:

答案 0 :(得分:6)

在您第一次setTimeout()来电时,请:

that.destroy(terms, curTerm + 1)

是一个函数调用表达式。对其进行评估,以构建一组参数值来调用setTimeout()

当你将它包装在一个匿名函数中时,该(匿名)函数被而不是调用,因为你没有用函数调用运算符作为后缀 - 带括号的参数列表。

因此:形式的表达

something ( p1, p2, ... pn )

表示在评估参数列表中的每个参数后调用“something”引用的函数,然后在更大的表达式上下文继续时使用该值。 始终表示在JavaScript中。没有语法可以说“这是我希望你稍后调用的函数,以及一些要传递的参数”。 (现在有一个函数 - 在函数原型上进行.bind() - 但没有特殊的语法。)

答案 1 :(得分:1)

这只是JavaScript语法的一部分。

function name() {}声明一个函数,name()调用它。您还可以使用语法(function (){})()立即调用匿名函数。

另请注意,您可以传递函数名称,否则匿名函数将适用于:

setTimeout(that.destroy, 1500)

当然,在这种情况下,您无法更改参数。

答案 2 :(得分:1)

当JavaScript解释器看到someFunction(param)时,它立即调用方法someFunction并将参数param传递给它。换句话说,当你这样做时:

setTimeout(someFunction(param), 1000);

...你正在通过setTimeout传递someFunction(param)的结果。您可以将someFunction作为第一类成员传递,如下所示:

setTimeout(someFunction, 1000, param);

这样,您就可以通过setTimeout传递someFunction的定义。请注意,在这种情况下通过param将无法在IE中工作。

另请参阅http://www.helephant.com/2008/08/19/functions-are-first-class-objects-in-javascript/