Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 关闭的合理用途?_Javascript_Closures - Fatal编程技术网

Javascript 关闭的合理用途?

Javascript 关闭的合理用途?,javascript,closures,Javascript,Closures,最近,我在我的公司看到了带有闭包函数的生产代码返回。例如return(function(){…}()),我不想看到这一点,但我不是一个权威的来源。我想我会问StackOverflow为什么以及何时使用这个好/坏 *注意* 假设您不担心名称空间污染,因为所有这些函数都已在其on闭包中 例1a: 函数foo(bar){ 返回{ x:1+巴, y:1巴, 持续时间:(函数(){ var i=0, len=5; var结果=0; 对于(;i

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

*注意*

假设您不担心名称空间污染,因为所有这些函数都已在其on闭包中

例1a:
函数foo(bar){
返回{
x:1+巴,
y:1巴,
持续时间:(函数(){
var i=0,
len=5;
var结果=0;
对于(;i
例1b:
功能条流程(bar){
var i=0;
var-len=5;
var结果=0;
对于(;i
例1c:
函数foo(bar){
var i=0;
var-len=5;
var结果=0;
对于(;i
观察: 示例1a:
如果需要,内部函数将利用闭包

示例1b:
在这种情况下,
barProcess
可能需要一些闭包,这可能会使参数列表很长,维护起来也有问题

示例1c:
每次调用都没有额外的函数创建。 (在我看来)它是最容易调试的

如果有人能给我一些技术上的理由,说明为什么应该使用示例a、b或c,那就太棒了



所以,我蹩脚的回答不能让我满意,所以我尝试了这个。我认为这使我的观察离得不太远。

我认为不可能在每一个简单的案例的例子a、b和c中选择一个明确的赢家

在您给出的示例中,版本(c)已经足够好了,因此我将使用它。这就是说,版本(a)将i、len和results的可验证性保持在一个更为严格的范围内,因此如果您希望将“x”和“y”与持续时间“b”更为分开,那么这绝对是一个好方法

我不喜欢仅仅出于组织或范围的原因而将事情拆分为单独的命名函数,就像您在示例(b)中所做的那样,因为这会使代码更复杂,更难理解。然而,如果BarProcess是一个实际的可重用抽象,您可以给它一个明确的名称,那么将其分开可能是一个好主意

假设您不担心名称空间污染,因为所有这些函数都已在其on闭包中


我想你在这里有点夸张。内部IFFE并不像外部IFFE那样被100%推荐,但更严格地限制范围仍然是完全可以的,我认为不值得为此与您的同事进行斗争。

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
    };
}
函数foo(bar){

对于(var i=0,results=0;这更适合。在我看来,当你需要保持某个值不变时,比如在循环中,你可以使用闭包,否则大部分时间都不需要闭包。当调用外部函数等没有实际意义时,自执行函数可能很方便。另外注意:当功能检测到本机fu时选择,则只需决定一次,而不是每次执行,您是可以使用该本机函数还是需要使用垫片/替代函数。
Example1a
确实会在每次执行时在内存中创建一个新函数,这似乎很愚蠢。既然该值已经在函数本身中关闭,为什么还要执行第二个function?我假设您使用的是像requirejs这样的东西,所有这些函数都将在define/require函数中关闭。版本a也慢了3倍(通过我提供给jsperf的链接)。这是需要注意的。@Michael:优化,这需要根据具体情况进行分析。我不确定如果你有一个复杂的函数,有很多函数调用,而不是你的小示例(这种情况下,使用版本a风格编写代码是值得的),那么两者的区别是否仍然相同。这是一个很好的观点。显然还有更多的东西需要测试!我不是故意简化c(这样人们就可以看到代码在所有三个地方都是相同的)这只是重复了我所说的,但并没有回答背后的“为什么”。当我说为什么我这样说:“你为什么吃东西?”,“因为我饿了”,“不,不,不,你为什么吃”,“哦,因为作为一个人,如果我不吃,我的身体会开始消化自己,我会变得困倦。”我在寻找第二种原因,更大的图景为什么。我的主要观点是帮助你理解,确切地说,没有一种情况,a/b/c,涉及“结束”——一个出现在
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)
    };
}
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
    };
}
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
    };
}