声明一个函数?

时间:2009-12-19 12:23:13

标签: javascript

我想知道这两个声明之间的区别是什么:

var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();


function delay {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
}

5 个答案:

答案 0 :(得分:3)

第一个函数声明使用匿名函数在变量timer上创建闭包,使用第二个匿名函数来避免使用timer污染全局名称空间。这是一种在JavaScript中的函数中实现数据隐藏和静态变量的简单方便的技术。

这个第一个/外部函数通常只使用一次,这就是为什么它永远不会被赋予名称,而是立即作为匿名函数执行。但是,如果您需要为多个事件创建多个计时器,则情况正好相反。

请考虑以下事项:

var delayBuilder = function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
}

现在:

var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();

相当于:

var delay = delayBuilder();

因此,如果您需要多次延迟(同时运行多个计时器),您可以这样做:

var delay1 = delayBuilder(),     delay2 = delayBuilder(),     ...     delayN = delayBuilder();

// And of course, used as:
delay1(callback, ms);

更通用的是,你有一个构建函数的函数,换句话说funcBuilderfunc(使用“func”,因为“function”是一个保留字)。

var func = funcBuilder(configurationifany);

因此,如果函数构建器更复杂,并且您想要构建它所构建的任何函数的单个抛弃实例,那么

funcBuilder(configurationifany)(etc, etc);

或者就你发布的代码而言(虽然这只是简单地包装setTimeout而仅仅是为了继续这个例子):

delayBuilder()(callback, ms);

它真的归结为用法。如果你不打算多次使用函数库,那么保持它并执行它是没有意义的,因为匿名函数更合适。如果需要构建该函数的多个实例,则保存对函数构建器的引用是有意义的。

答案 1 :(得分:1)

在第二种情况下,您将丢弃返回的函数。

如果我理解你的问题,那就是你想要第二个案例

function delay() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
}

然后不同的是存储在延迟中的代码不会被执行。如果你稍后调用延迟,那么它将是等价的,差异将是函数的匿名性和delay的值(在第一种情况下它是内部函数,在第二种 - 外部函数中)。

答案 2 :(得分:1)

让函数返回另一个函数的目的是为函数外部声明的变量创建一个范围,而不必全局声明它们。外部函数在创建后立即执行(通过在声明之后放置括号),因此返回内部函数并将其赋值给变量。

在第一个示例中,timer变量用于内部函数,因此创建了一个包含变量的闭包。当您稍后使用该函数时,它仍然可以访问timer变量,尽管它不在函数本身内部。执行外部函数以便返回内部函数,并将其分配给delay变量。

讨论两个声明之间的区别是没有意义的。第二个声明只声明了外部函数,但它既没有存储也没有执行,所以它就被抛弃了。

编辑:
在您更新的问题中(如果通过在第二个声明中的函数名称之后添加括号来更正),则第二个声明是一个函数,它返回在第一个声明中分配给变量的相同结果。因此,要获得相同的结果,您必须调用函数并将返回值赋给变量:

var d = delay();

现在d变量包含的内容与第一个示例中的delay变量相同。

答案 3 :(得分:0)

第一种情况使用函数表达式生成一个匿名函数,该函数立即被调用,它将一个timer变量包装在一个闭包中并返回另一个函数(用函数表达式生成)。

第二种情况是语法错误(因为函数表达式没有上下文而函数声明没有名称)。

因为你现在已经编辑了它......

第二种情况现在使用函数声明,但不调用函数。所以它现在将执行匿名函数所做的事情(而不是返回的函数所做的事情)。

答案 4 :(得分:0)

在第一种情况下,您创建然后调用匿名函数。在第二个中,您创建一个匿名函数,但既不调用它也不将其保存在变量中。我甚至不确定这是合法的。