闭合的合理用途?

时间:2013-05-17 22:14:56

标签: javascript closures

最近,我在我的公司看到生产代码返回带闭包功能。如return (function() {...}());我不喜欢看到这一点,但我不是权威来源。我以为我会问StackOverflow为什么以及何时使用这个好/坏。

*注意*

说你不关心命名空间污染,因为所有这些功能都已经在关闭状态。

Example1a:

function foo(bar) {
    return {
        x: 1 + bar,
        y: 1 - bar,
        duration: (function() {
            var i = 0,
                len = 5;
            var results = 0;

            for (; i < bar; i++) {
                results += 1 + (results * bar);
            }

            return results;
        }())
    };
}

Example1b:

function barProcess(bar) {
    var i = 0;
    var len = 5;
    var results = 0;

    for (; i < bar; i++) {
         results += 1 + (results * bar);
    }

    return results;
}

function foo(bar) {
    return {
        x: 1 + bar,
        y: 1 - bar,
        duration: barProcess(bar)
    };
}

Example1c:

function foo(bar) {
    var i = 0;
    var len = 5;
    var results = 0;

    for (; i < bar; i++) {
         results += 1 + (results * bar);
    }

    return {
        x: 1 + bar,
        y: 1 - bar,
        duration: results
    };
}

观察:

Example1a:
如果有需要,内部函数会利用闭包。

Example1b:
如果barProcess可能需要一些关闭,这可能会使参数列表变长并且有问题需要维护。

Example1c:
每次调用都不会创建额外的函数。 调试最容易(在我看来)。

如果有人可以给我一些技术原因,请说明为什么应该使用示例a,b或c,那将是非常棒的。


所以,我的蹩脚回答并不能让我满意,所以我试过了。 JS Perf Tests。我认为我的观察结果并不太远。

2 个答案:

答案 0 :(得分:0)

对于每个简单的案例,我认为不可能在例子a,b和c之间选择一个明显的赢家。

在你给出的例子中,版本(c)足够好所以我会继续使用它。也就是说,版本(a)将i,len和结果变量保持在更紧凑的范围内,因此如果你想让“x”和“y”与持续时间“b”更加分离,它肯定是一个很好的方法。

我不喜欢将内容分成单独的命名函数,只是出于组织或范围的原因,就像你在例子(b)中所做的那样,因为它往往会使代码更复杂,更难以遵循。但是,如果barProccess是一个实际可重用的抽象,你可以给出一个明确的名称,然后将它保持分离可能是一个好主意。

  

说你不关心命名空间污染,因为所有这些功能都已经在关闭状态。

我觉得你在这里有点夸张。内部IFFE不是100%推荐,就像外部IFFE一样,但限制范围更加完美仍然完全没问题,而且我认为它不值得与你的同事作战。

答案 1 :(得分:0)

1a:没有形成闭包,因为外部函数foo()在内部函数执行时没有返回。内部函数是一个匿名的“自执行”子例程。虽然自执行函数可以形成一个闭包,但这个函数既不需要也不需要。这是构造代码的一种稍微“炫耀”的方式。

1b:没有形成闭包,因为外部函数foo()直接调用命名函数barProcess(),它返回一个数值,而不是函数。如果还要从代码中的其他地方调用barProcess(),这种方法将非常有用。

1c:没有形成闭合。 foo()包含一个直接的代码块,这个代码块很容易理解并且可以完成这项工作。由于javascript for循环没有自己的范围,foo()将简化为:

function foo(bar) {
    for(var i=0, results=0; i<bar; i++) {
         results += 1 + (results * bar);
    }
    return {
        x: 1 + bar,
        y: 1 - bar,
        duration: results
    };
}