57

When you wrap your JavaScript code in a function like this:

(function(){

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


})();

I noticed that this fixes scoping problems for me on a lot of web pages. What is this practice called?

4

7 回答 7

37

The pattern is called self-invocation, a self-invoking function. It can create a closure, but that is an effect of the pattern (perhaps the intended effect), not the pattern itself.

于 2010-09-15T18:01:03.513 回答
20

To clarify a bit for the comments below, most of the time it's creating a closure, it keeps your variables scoped to that local closure, as to not create global variables, it both keeps things clean and avoids any potential unwanted changes to those variables.

There are some excellent answers here that explain the why a bit more: How does a javascript closure work?

It's only a creating closure when something inside that scope is exposed to an outer scope, which is usually the case, but I can't be sure for your example without seeing more code. If nothing is exposed then no closure's created...otherwise it's just an anonymous function executing immediately.

The })(); format at the end, as opposed to }); is actually calling that closure to execute immediately, with no parameters. If you had something in it, for example })(something); then that something would be passed as the first argument here: (function(somethingParam){.

于 2010-09-15T17:51:18.777 回答
15

The wrapping function is called an anonymous (it has no name and it isn't assigned to a variable) self-executing (it executes immediately, by itself) function.

I don't remember seeing an exact name for this pattern, but it prevents variable from leaking into global scope.

于 2010-09-15T17:51:37.960 回答
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();
}

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

// 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 使用!版本)。

于 2010-12-27T16:00:24.040 回答
6

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

于 2010-09-30T21:17:19.537 回答
4

这种做法叫什么?

它被称为立即调用的函数表达式,简称:IIFE。它在表达式中定义了一个函数,然后它自己执行(不将函数分配给任何标识符)。有时也称为立即执行函数表达式(IEFE)。

在 Ben Alman 写关于它们的博客文章之前,它们也被称为自调用(匿名)函数,从那时起这个术语就变得不常见了。它在技术上是不精确的,暗示了一个实际上并没有发生的递归调用。

有关语法的详细信息,请参阅解释封装的匿名函数语法自动执行匿名 JavaScript 函数的括号位置?.

我注意到这解决了我在很多网页上的范围界定问题。

是的,这种模式的目的是通过执行一个函数来引入一个额外的范围。

该模式有时也使用返回值扩展,称为(显示)模块模式,或者使用函数的名称来允许递归调用。

于 2014-07-20T19:44:47.497 回答
1

它的存在时间比“模式”还要长。这是 scheme/lisp 中的一个常见习惯用法,主要用于封装,尤其是在进行元编程时。

于 2010-12-28T18:30:30.693 回答