这种做法在 JavaScript 中称为什么?

IT技术 javascript design-patterns terminology iife
2021-01-13 18:36:14

当您将 JavaScript 代码包装在这样的函数中时:

(function(){

  var field = ...;
  function doSomthing(){...
  ...


})();

我注意到这在很多网页上为我解决了范围界定问题。这种做法叫什么?

6个回答

该模式称为self-invocation,一种自调用函数它可以创建一个闭包,但这是模式的效果(也许是预期的效果),而不是模式本身。

@Nick Craver:见编辑。我的意思是一个效果,但预期的效果。
2021-03-17 18:36:14
我不确定您如何称其为副作用……如果您想立即执行代码(而不是闭包),为什么首先将其包装在函数中?这是一种直接而有意的效果。
2021-03-19 18:36:14
@slebetman - 你没有阅读上面的评论,或者我 20 分钟前更新的答案,我澄清了这一点:“当该范围内的某些内容暴露于外部范围时,这只是一个闭包,这通常是这种情况,但是如果没有看到更多代码,我无法确定您的示例。如果没有公开任何内容,则不会创建闭包……否则它只是一个立即执行的匿名函数。”
2021-03-24 18:36:14
@Nick:关闭是一种可能的副作用。函数不是闭包。没有名称的函数称为匿名函数,不熟悉函数式语言的人错误地将其称为闭包。在 javascript 中,大括号(..)声明的东西是表达式,所以这是一个匿名函数表达式。所有表达式都返回一些东西。在函数表达式的情况下,它返回对函数的引用。以上这些都不是传统意义上的闭包。闭包是函数之间共享的变量,而不是函数本身。
2021-03-31 18:36:14
@Nick:即便如此,它也不是闭包,而是匿名函数。尽管闭包依赖于函数,但这两个概念是分开的。
2021-04-10 18:36:14

为了澄清下面的评论,大多数情况下它是创建一个闭包,它使您的变量作用域限于该局部闭包,因为不创建全局变量,它既保持事物干净,又避免对这些变量进行任何潜在的不需要的更改。

这里有一些很好的答案可以解释为什么多一点:javascript 闭包如何工作?

当该范围内的某些内容暴露给外部范围时,这只是一个创建闭包,通常是这种情况,但是如果没有看到更多代码,我无法确定您的示例。如果什么都没有暴露,那么就不会创建闭包……否则它只是一个立即执行的匿名函数。

最后的})();格式,而不是});实际上调用该闭包立即执行,没有参数。例如,如果你有一些东西,})(something);那么something它将作为第一个参数传递在这里:(function(somethingParam){

严格来说,闭包是函数的副作用。这不是一个闭包,它是一个函数。事实上,在这种情况下甚至可能没有创建闭包,因为无法从外部访问函数的内容。请参阅jibbering.com/faq/notes/closures
2021-03-24 18:36:14
@Nick:函数不是闭包。不要混淆你的术语。闭包是函数共享的变量。一个函数可以创建一个闭包,但它本身并不是一个闭包。这就像将烤箱称为蛋糕。蛋糕不是烤箱,但烤箱可以用来烤蛋糕。
2021-03-25 18:36:14
@Jani - 这就是闭包的作用......它专门用于(在这种情况下)从外部隐藏内容,同时让内部的任何东西都可以访问它们。甚至您提供的链接也给出了这个确切的定义:“闭包的简单解释是 ECMAScript 允许内部函数;其他函数的函数体内部的函数定义和函数表达式。并且这些内部函数被允许访问所有局部变量、参数和在其外部函数中声明的内部函数。”
2021-03-30 18:36:14
@Nick,您引用的那一行是指标识符解析过程的工作方式,而不是专门针对闭包的形成,继续引用:“当这些内部函数之一在函数外部可访问时,就会形成闭包它包含在其中,以便它可以在外部函数返回后执行。” 因此,如果没有内部函数可供外部使用,则不会形成闭包—— @Jani 指出的——,IMO现在有时会过度使用术语闭包
2021-04-01 18:36:14
@Nick,是的,这个例子不完整。是的,您几乎总是向外部公开一些东西,在函数(或包含引用本地函数的属性的对象)的情况下,会形成一个闭包。感谢您的澄清。
2021-04-06 18:36:14

包装函数被称为匿名(它没有名称,也没有分配给变量)自执行(它自己立即执行)函数。

我不记得看到这种模式的确切名称,但它可以防止变量泄漏到全局范围内。

它不自称。该函数恰好被立即调用。没有递归进行,没有“自我执行”。
2021-03-14 18:36:14
我称之为匿名作用域函数
2021-04-04 18:36:14
我个人称其为自调用函数。当我说出这句话时,最有经验的 javascript 开发人员就知道我在说什么了。
2021-04-08 18:36:14

Ben Alman 就这种“模式”的常用术语提出了一个有趣的论点。

他的博客文章在这里 (http://benalman.com/news/2010/11/immediately-invoked-function-expression/)

如果他的帖子对你来说太长,这里是我的总结(我仍然建议阅读它,因为这个总结遗漏了很多):

如果您希望命名函数自执行/调用,它应该如下所示:

// Hello, my name is "foo". I am a named function.
// When I am invoked I invoke my self when I am invoked.
function foo(){
   foo();
}

如果您希望匿名函数自执行/调用,它应该如下所示:

// Hello, I have no name...
//   (though I am assigned to the variable "foo" it's not who I am).
// When I am invoked I invoke my self when I am invoked.
// In ECMAScript 5 I no longer work. :-(
var foo = function(){
    arguments.callee();
};

如果您希望立即执行/调用匿名函数,它应该如下所示:

// Hello, I have no name. I am immediately invoked.
// People sometimes call me a "self-invoking anonymous function"...
//    even though I don't invoke myself.
// Ben Alman calls me an "Immediately-Invoked Function Expression"...
//    or "iffy" for short.
(function(){ /...code.../ }());

我个人对这个问题的看法:

其他答案是正确的;您所问的通常称为“自调用匿名函数”。
但是,该术语并不能准确反映实际发生的情况。“立即调用的函数表达式”(简称“iffy”)似乎是一个更合适的术语。


有趣的事实给你的朋友留下深刻印象:

你也可以像这样创建一个 iffy:

!function(){
   alert("immediately invoked!");
}();

或者

+function(){
   alert("immediately invoked!");
}();

或者如果你真的很疯狂(例子):

!1%-+~function(){
   alert("immediately invoked!");
}();

在大多数浏览器中(如果不是全部,我不确定)并且效果将相同(facebook 使用该!版本)。

我不建议使用这些“快捷方式”,因为大多数开发人员都不知道它,而且我不确定浏览器的兼容性。跨浏览器测试它,如果它在任何地方都可以工作,你总是可以这样做:!(function(){}());所以你仍然可以使用漂亮的!和广为人知的“立即调用函数表达式”。
2021-04-05 18:36:14

Douglas Crockford 和 YUI 团队将其称为module模式

module模式比这更具体。它使用“闭包”作为向在初始(立即)调用时返回的对象或函数提供私有方法和变量的一种方式。
2021-04-09 18:36:14
所以如果它返回一个对象(可能隐藏在局部变量中的私有状态),它只算作一个module?太糟糕了。
2021-04-09 18:36:14