IIFE 作为闭包
Posted
技术标签:
【中文标题】IIFE 作为闭包【英文标题】:IIFEs as closures 【发布时间】:2017-12-22 09:54:11 【问题描述】:在You Don't Know javascript 系列中,IIFE 的 1/3 被描述为本身不是闭包,但前提是它们在其词法范围之外执行:
第 3 章介绍了 IIFE 模式。虽然人们常说 IIFE(单独)是观察到的关闭的一个例子,我会有点 不同意,根据我们上面的定义。
这段代码“有效”,但严格来说并不是对闭包的观察。 为什么?因为函数(我们在这里命名为“IIFE”)没有被执行 超出其词法范围。它仍然在同一个地方被调用 声明的范围(也包含的封闭/全局范围 一种)。 a 是通过正常的词法范围查找找到的,而不是真正通过 关闭。
var a = 2;
(function IIFE() // not actually a "closure"
console.log( a );
)();
在SO post 中,给出了以下 sn-p 作为闭包的示例:
for (var i = 0; i < someVar.length; i++)
(function (i)
window.setTimeout(function ()
alert("Value of i was "+i+" when this timer was set" )
, 10000);
)(i);
我试图根据闭包的定义来理解这一点(定义见this medium article):
要使用闭包,只需在另一个函数中定义一个函数,然后 暴露它。要公开一个函数,请将其返回或传递给另一个函数 功能。 ...
内部函数可以访问外部变量 函数作用域,即使在外部函数返回之后。
我知道闭包是一个“有状态的函数”,它是
一种“记住”并继续访问函数作用域的方法(它的 变量),即使函数完成运行。
所以在这个例子中,我看到循环的i
在传递到关闭的 IIFE 时被记住了。
我的问题是:
“传递给另一个函数或返回”部分发生在哪里?我的猜测是,因为 IIFE 被传递到窗口,所以 IIFE 能够在每次迭代时记住外部 i
for 循环值?
基本上,我的理解是,闭包定义为在垃圾收集器清理外部范围后记住外部范围的值,并且它的用法是通过返回闭包并在其词法范围之外访问它来公开闭包。它是否正确?那么“在词法范围之外访问它”发生在哪里呢?
【问题讨论】:
一个更好的闭包 IIFE 示例是let plus3 = (x => y => x + y)(3);
。这里变量x
被关闭了。当您使用值 3 调用它时,它会返回一个函数,该函数接受另一个参数 y 并向其添加 3。
我不确定一个闭包是否只是基于何时/何地被调用...
@OliverCharlesworth 我认为 OP 引用的作者的意思是“当它实际上并没有关闭周围范围内任何感兴趣的东西时”。
@growler window
与它无关,传递给setTimeout
的所有匿名函数都在循环中关闭了变量i
。
在 (function (i) ... )(i)
示例中,该 IIFE 的目的是创建一个本地(参数)变量,以便每个 setTimeout
回调引用一个不同的名为 i
的本地变量同一个全球i
。传入setTimeout
的函数覆盖了由周围IIFE 中名为i
的参数创建的i
。
【参考方案1】:
在这个例子中,我看到循环的
i
在传递到关闭的 IIFE 时被记住
没有。 IIFE 仅提供要记住的 i
值的范围。正如您引用的引号所述,IIFE 函数不是闭包。 使用 i
的函数表达式是闭包:
(function IIFE(i)
// this is the scope of i
window.setTimeout(function closure()
// this function closes over i
alert("Value of my local 'i' is still "+i+" even after 10 seconds");
, 10000);
)(0);
// ^ this is some arbitrary value passed to the IIFE - it could have been a loop variable
“传递给另一个函数或返回”部分发生在哪里?
这是传递给setTimeout
的closure
函数,它将从通常不再定义i
的地方回调它——如果它不是闭包的话。
【讨论】:
谢谢你。我已经在我的问题下面的 cmets 中解决了它:)以上是关于IIFE 作为闭包的主要内容,如果未能解决你的问题,请参考以下文章