繁体   English   中英

从匿名包装器返回一个函数?

[英]Return a function from the anonymous wrapper?

我试图理解代码

for(var i = 0; i < 10; i++) {
    setTimeout((function(e) {
        return function() {
            console.log(e);
        }
    })(i), 1000)
}

从这里http://bonsaiden.github.com/JavaScript-Garden/#function.closures

我理解这种方法:

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 1000);
    })(i);
}

任何人都可以通过解释第一个来帮助我吗?

我将尝试解释我如何理解第一个,

first i is 0,
setTimeout is called,
self calling function "function(e)" is called with i=0,
Im stuck!! what happens when this function returns a function?

所有第一个返回的函数将在超时发生后调用。

它的目的是为for循环的每次迭代创建一个子范围,以便在每次迭代时不会覆盖递增i

更多解释:

让我们把它分成两个不同的部分:

for(var i = 0; i < 10; i++) {
    setTimeout((function(e) {
        return function() {
            console.log(e);
        }
    })(i), 1000)
}

这是第一篇:

for(var i = 0; i < 10; i++) {
    setTimeout(function(){
        console.log(i); //9-9
    },1000);
}

现在,当你运行这个循环时,你将总是得到包含9而不是0到9的console.log()。这是因为每个setTimeout都使用与i相同的引用。

如果将setTimeout的一部分包装在匿名函数中,它会为每次迭代创建一个范围,允许每个setTimeout拥有它自己的i值。

for(var i = 0; i < 10; i++) {
    setTimeout((function(i) {
        return function() {
            console.log(i); // 0-9
        }
    })(i), 1000)
}

setTimeout中的外部函数立即执行,第一次迭代的i为0,第二次为1,等等。然后该函数返回一个函数,该函数是setTimeout使用的函数。 正在使用i的不同值为循环的每次迭代生成并返回函数。

两者都得到相同的结果:使用要调用的函数调用setTimeout,该函数在控制台上写入0到9之间的数字。 两者都使用嵌套函数将i的当前值放入闭包中,因此最终不会记录10 9。

第一个代码选择让函数返回setTimeout将调用的函数。 第二个更改嵌套顺序,以便关闭函数调用setTimeout本身。 净效果是一样的。

除了风格和个人选择之外,我没有理由选择其中一个。

“你可以查看更新的问题,指明我在哪里感到困惑”

好的,这是一个很长的解释。 请记住, setTimeout()的第一个参数需要是对指定延迟后要执行的函数的引用。 最简单的情况是命名一个在别处定义的函数:

function someFunc() {
   console.log("In someFunc");
}

setTimeout(someFunc, 100);

注意someFunc在将其作为参数传递给setTimeout时没有括号,因为需要对函数本身的引用。 对比:

setTimeout(someFunc(), 100);   // won't work for someFunc() as defined above

使用括号,它调用 someFunc()并将其返回值传递给setTimeout 但是我对someFunc()定义并没有明确地返回一个值,所以它隐式返回undefined - 就像说setTimeout(undefined, 100)

但是如果更改someFunc()以返回函数而不是返回undefined ,它将起作用:

function someFunc() {
   return function() {
      console.log("In the function returned from someFunc");
   };
}

所以现在(最后)我们来看你问题的代码:

setTimeout((function(e) {
    return function() {
        console.log(e);
    }
})(i), 1000)

它不是通过名称引用函数并将其称为someFunc(i)而是定义一个匿名函数并立即将其作为(function(e) {})(i)调用。 该匿名函数返回另一个函数,它返回的函数成为setTimeout()的实际参数。 当时间到时,它将返回将要执行的函数。 因为返回的(内部)函数是在(外部)匿名函数的范围内定义的,所以它可以访问e参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM