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

ste*_*bot 57 javascript design-patterns terminology

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

(function(){

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


})();
Run Code Online (Sandbox Code Playgroud)

我注意到这在很多网页上为我修复了范围问题.这种做法叫做什么?

pal*_*wim 38

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

  • @Nick:封闭是一种可能的副作用.一个函数**不是**一个闭包.没有名称的函数称为匿名函数,被不熟悉函数式语言的人错误地称为闭包.在javascript中,在大括号`(..)`中声明的东西是表达式,因此这是一个匿名函数表达式.所有表达都会返回一些 在函数表达式的情况下,它返回对函数的引用.上述所有内容都不是传统意义上的闭包.闭包是函数之间共享的变量,而不是函数本身. (7认同)
  • @Nick:即便如此,它不是一个闭包,它是一个匿名函数.虽然闭包依赖于函数,但这两个概念是分开的. (2认同)

Nic*_*ver 20

为了澄清下面的注释,大部分时间它都在创建一个闭包,它将你的变量限定为该局部闭包,因为它不会创建全局变量,它既可以保持清洁,又可以避免对这些变量进行任何潜在的不必要的更改.

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

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

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

  • 严格来说,闭包是函数的副作用.这不是一个闭包,它是一个功能.实际上,在这种情况下甚至可能没有创建闭包,因为函数的内容不能从外部访问.见http://jibbering.com/faq/notes/closures/ (12认同)
  • @Nick,你引用的行指的是标识符解析过程的工作方式,而不是特别是形成一个闭包,继续引用:"当一个内部函数之一可以访问时,就会形成一个*闭包*包含它的函数,以便在外部函数返回后执行它." 因此,如果没有*inner*函数可用于外部,则不会形成闭包 - @Jani指出 - ,IMO术语*闭包*有时会被过度使用. (3认同)
  • @Nick,是的,这个例子不完整.是的,在*function*(或包含引用本地函数的属性的对象)的情况下,几乎总是向外部暴露一些东西,形成一个闭包.谢谢你的澄清. (3认同)
  • @Jani - 这就是封闭所做的......它专门用于(在这种情况下)从外部隐藏内容,同时让内容可以访问.甚至你提供的链接也提供了这个*exact*定义:"Closure的简单解释是ECMAScript允许内部函数;函数定义和函数表达式在其他函数的函数内部.并且这些内部函数允许访问所有局部变量,参数和声明的内部函数在它们的外部函数中." (2认同)
  • @Nick:一个函数**不是**一个闭包.不要混淆你的术语.闭包是函数共享的变量.函数可以**创建一个闭包,但它本身不是一个闭包.这就像把烤箱叫做蛋糕.蛋糕不是烤箱,而是烤箱可以用来烤蛋糕. (2认同)
  • @slebetman - 我不相信我说一个函数*是*一个闭包,你不会在那里得到任何辩论(事实上,它是在答案的第一行:"**创建**一个闭包" ).我说这可能是***创建**一个闭包,因为这是它的主要目的(但是,再一次,我们无法分辨看到整个代码).如果你没有阅读,我道歉,我认为半个小时前的澄清清楚地表达了这一点,我会尝试改进它以使其更清晰. (2认同)
  • @Nick,在你的例子中,但是根据我的经验,大多数时候人们使用这种模式,他们只访问全局变量(无论是jquery,窗口,文档等).因此,这种模式通常不使用闭包,因此我们不需要仅仅因为它是"嘻哈术语"而将人们与这个术语混淆.另外,我觉得困扰我的是虽然可能会使用闭包,但这并不是*必要*功能.是的,变量也被使用了,但是我们不把这个模式称为变量,对吗? (2认同)
  • @Marcel:我不确定Flanagan是谁,但是Landin的原始论文将闭包描述为具有环境和变量,并使用术语匿名函数来指代函数本身.(该论文可在线免费访问.) (2认同)

Jan*_*nen 15

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

我不记得看到这个模式的确切名称,但它阻止变量泄漏到全局范围.

  • 我称之为匿名范围函数 (2认同)
  • 它不会自称.恰好恰好立即调用该函数.没有递归,没有"自动执行". (2认同)

Dav*_*och 12

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();
}
Run Code Online (Sandbox Code Playgroud)

如果你想让一个匿名函数自动执行/调用它应该如下所示:

// 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();
};
Run Code Online (Sandbox Code Playgroud)

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

// 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.../ }());
Run Code Online (Sandbox Code Playgroud)

我对此事的看法:

其他答案都是正确的; 你所问的通常被称为"自我调用匿名函数".
但是,该术语并不能准确反映真实情况; "立即调用函数表达式"(简称"iffy")似乎是一个更合适的术语.


有趣的事实来打动你的朋友:

您也可以像这样创建一个Iffy:

!function(){
   alert("immediately invoked!");
}();
Run Code Online (Sandbox Code Playgroud)

要么

+function(){
   alert("immediately invoked!");
}();
Run Code Online (Sandbox Code Playgroud)

或者如果你真的是 cRaZy(例子):

!1%-+~function(){
   alert("immediately invoked!");
}();
Run Code Online (Sandbox Code Playgroud)

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


Sea*_*lan 6

Douglas Crockford和YUI团队称之为模块模式.