JavaScript 中的 (function() { } )() 构造是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8228281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:12:41  来源:igfitidea点击:

What is the (function() { } )() construct in JavaScript?

javascriptiife

提问by Exitos

I used to know what this meant, but I'm struggling now...

我以前知道这是什么意思,但我现在很挣扎......

Is this basically saying document.onload?

这基本上是说document.onload吗?

(function () {

})();

回答by gion_13

It's an Immediately-Invoked Function Expression, or IIFEfor short. It executes immediately after it's created.

它是一个立即调用的函数表达式,简称IIFE。它在创建后立即执行。

It has nothing to do with any event-handler for any events (such as document.onload).
Consider the part within the first pair of parentheses: (function(){})();....it is a regular function expression. Then look at the last pair (function(){})();, this is normally added to an expression to call a function; in this case, our prior expression.

它与任何事件(例如document.onload)的任何事件处理程序无关。
考虑第一对括号内的部分:....它是一个正则函数表达式。再看最后一对,这个一般是加在表达式中调用函数;在这种情况下,我们的先前表达式。(function(){})();(function(){})();

This pattern is often used when trying to avoid polluting the global namespace, because all the variables used inside the IIFE (like in any other normalfunction) are not visible outside its scope.
This is why, maybe, you confused this construction with an event-handler for window.onload, because it's often used as this:

当试图避免污染全局命名空间时,经常使用这种模式,因为 IIFE 内部使用的所有变量(就像任何其他普通函数一样)在其范围之外是不可见的。
这就是为什么,也许,您将此构造与 for 的事件处理程序混淆window.onload,因为它通常用作:

(function(){
  // all your code here
  var foo = function() {};
  window.onload = foo;
  // ...
})();
// foo is unreachable here (it's undefined)

Correction suggested by Guffa:

Guffa建议的更正

The function is executed right after it's created, not after it is parsed. The entire script block is parsed before any code in it is executed. Also, parsing code doesn't automatically mean that it's executed, if for example the IIFE is inside a function then it won't be executed until the function is called.

该函数在创建后立即执行,而不是在解析后执行。整个脚本块在其中的任何代码被执行之前被解析。此外,解析代码并不自动意味着它已被执行,例如,如果 IIFE 在一个函数内,那么在调用该函数之前它不会被执行。

UpdateSince this is a pretty popular topic, it's worth mentioning that IIFE's can also be written with ES6's arrow function(like Gajushas pointed out in a comment) :

更新由于这是一个非常受欢迎的话题,值得一提的是,IIFE 也可以用ES6 的箭头函数来编写(就像Gajus在评论中指出的那样):

((foo) => {
 // do something with foo here foo
})('foo value')

回答by Guffa

It's just an anonymous function that is executed right after it's created.

它只是一个在创建后立即执行的匿名函数。

It's just as if you assigned it to a variable, and used it right after, only without the variable:

这就像你将它分配给一个变量,然后在没有变量的情况下使用它:

var f = function () {
};
f();

In jQuery there is a similar construct that you might be thinking of:

在 jQuery 中,您可能会想到类似的构造:

$(function(){
});

That is the short form of binding the readyevent:

这是绑定ready事件的简短形式:

$(document).ready(function(){
});

But the above two constructs are not IIFEs.

但是上述两个构造不是IIFE

回答by u911838

An immediately-invoked function expression (IIFE) immediately calls a function. This simply means that the function is executed immediately after the completion of the definition.

立即调用函数表达式 (IIFE) 立即调用函数。这只是意味着函数在定义完成后立即执行。

Three more common wordings:

三个比较常见的说法:

// Crockford's preference - parens on the inside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
}());

//The OPs example, parentheses on the outside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
})();

//Using the exclamation mark operator
//https://stackoverflow.com/a/5654929/1175496
!function() {
  console.log('Welcome to the Internet. Please follow me.');
}();

If there are no special requirements for its return value, then we can write:

如果对其返回值没有特殊要求,那么我们可以这样写:

!function(){}();  // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}();  // => NaN

Alternatively, it can be:

或者,它可以是:

~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();

You can even write:

你甚至可以写:

new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required

回答by solendil

It declares an anonymous function, then calls it:

它声明了一个匿名函数,然后调用它:

(function (local_arg) {
   // anonymous function
   console.log(local_arg);
})(arg);

回答by Naftali aka Neal

That is saying execute immediately.

也就是说立即执行。

so if I do:

所以如果我这样做:

var val = (function(){
     var a = 0;  // in the scope of this function
     return function(x){
         a += x;
         return a;
     };
})();

alert(val(10)); //10
alert(val(11)); //21

Fiddle: http://jsfiddle.net/maniator/LqvpQ/

小提琴:http: //jsfiddle.net/maniator/LqvpQ/



Second Example:

第二个例子:

var val = (function(){
     return 13 + 5;
})();

alert(val); //18

回答by Usman

That construct is called an Immediately Invoked Function Expression (IIFE)which means it gets executed immediately. Think of it as a function getting called automatically when the interpreter reaches that function.

该构造称为立即调用函数表达式 (IIFE),这意味着它会立即执行。将其视为当解释器到达该函数时自动调用的函数。

Most Common Use-case:

最常见的用例:

One of its most common use cases is to limit the scope of a variable made via var. Variables created via varhave a scope limited to a function so this construct (which is a function wrapper around certain code) will make sure that your variable scope doesn't leak out of that function.

它最常见的用例之一是限制通过var. 通过创建的变量var的范围仅限于函数,因此此构造(它是某些代码的函数包装器)将确保您的变量范围不会从该函数泄漏。

In following example, countwill not be available outside the immediately invoked function i.e. the scope of countwill not leak out of the function. You should get a ReferenceError, should you try to access it outside of the immediately invoked function anyway.

在下面的示例中,count在立即调用的函数之外将不可用,即范围count不会泄漏到函数之外。如果ReferenceError您尝试在立即调用的函数之外访问它,您应该得到, 。

(function () { 
    var count = 10;
})();
console.log(count);  // Reference Error: count is not defined

ES6 Alternative (Recommended)

ES6 替代方案(推荐)

In ES6, we now can have variables created via letand const. Both of them are block-scoped (unlike varwhich is function-scoped).

在 ES6 中,我们现在可以通过let和创建变量const。它们都是块范围的(与var函数范围的不同)。

Therefore, instead of using that complex construct of IIFE for the use case I mentioned above, you can now write much simpler code to make sure that a variable's scope does not leak out of your desired block.

因此,无需在我上面提到的用例中使用复杂的 IIFE 构造,现在您可以编写更简单的代码来确保变量的作用域不会泄漏到您想要的块之外。

{ 
    let count = 10;
}
console.log(count);  // ReferenceError: count is not defined

In this example, we used letto define countvariable which makes countlimited to the block of code, we created with the curly brackets {...}.

在这个例子中,我们用来let定义count变量,它count限制了我们用大括号创建的代码块{...}

I call it a “Curly Jail”.

我称之为“卷曲监狱”。

回答by Gurucharan M K

(function () {
})();

This is called IIFE (Immediately Invoked Function Expression). One of the famous JavaScript design patterns, it is the heart and soul of the modern day Module pattern. As the name suggests it executes immediately after it is created. This pattern creates an isolated or private scope of execution.

这称为 IIFE(立即调用函数表达式)。著名的 JavaScript 设计模式之一,它是现代模块模式的核心和灵魂。顾名思义,它在创建后立即执行。这种模式创建了一个独立的或私有的执行范围。

JavaScript prior to ECMAScript 6 used lexical scoping, so IIFE was used for simulating block scoping. (With ECMAScript 6 block scoping is possible with the introduction of the letand constkeywords.) Reference for issue with lexical scoping

ECMAScript 6 之前的 JavaScript 使用词法范围,因此 IIFE 用于模拟块范围。(通过引入letconst关键字,ECMAScript 6 块作用域是可能的。) 词法作用域问题的参考

Simulate block scoping with IIFE

使用 IIFE 模拟块范围

The performance benefit of using IIFE's is the ability to pass commonly used global objects like window, document, etc. as an argument by reducing the scope lookup. (Remember JavaScript looks for properties in local scope and way up the chain until global scope). So accessing global objects in local scope reduces the lookup time like below.

使用IIFE的的性能优势是通过像常用的全局对象的能力windowdocument通过减少范围查找等作为参数。(请记住,JavaScript 在本地范围内查找属性,并在链中查找直到全局范围)。因此,在局部范围内访问全局对象会减少查找时间,如下所示。

(function (globalObj) {
//Access the globalObj
})(window);

回答by Aldo Stracquadanio

No, this construct just creates a scope for naming. If you break it in parts you can see that you have an external

不,这个构造只是创建了一个命名范围。如果你把它分成几部分,你可以看到你有一个外部

(...)();

That is a function invocation. Inside the parenthesis you have:

那是一个函数调用。在括号内你有:

function() {}

That is an anonymous function. Everything that is declared with varinside the construct will be visible only inside the same construct and will not pollute the global namespace.

那是一个匿名函数。在构造中使用var声明的所有内容仅在同一构造中可见,并且不会污染全局命名空间。

回答by Santosh Pillai

This is an Immediately Invoked Function Expression in Javascript:

这是 Javascript 中的立即调用函数表达式:

To understand IIFE in JS, lets break it down:

要理解 JS 中的 IIFE,让我们分解一下:

  1. Expression: Something that returns a value
    Example: Try out following in chrome console. These are expressions in JS.
  1. 表达式:返回值的东西
    示例:在 chrome 控制台中尝试以下操作。这些是 JS 中的表达式。
a = 10 
output = 10 
(1+3) 
output = 4
a = 10 
output = 10 
(1+3) 
output = 4
  1. Function Expression:
    Example:
  1. 函数表达式
    示例:
// Function Expression 
var greet = function(name){
   return 'Namaste' + ' ' + name;
}

greet('Santosh');
// Function Expression 
var greet = function(name){
   return 'Namaste' + ' ' + name;
}

greet('Santosh');

How function expression works:
- When JS engine runs for the first time (Execution Context - Create Phase), this function (on the right side of = above) does not get executed or stored in the memory. Variable 'greet' is assigned 'undefined' value by the JS engine.
- During execution (Execution Context - Execute phase), the funtion object is created on the fly (its not executed yet), gets assigned to 'greet' variable and it can be invoked using 'greet('somename')'.

函数表达式的工作原理:
- 当JS引擎第一次运行时(执行上下文-创建阶段),这个函数(在上面=右侧)不会被执行或存储在内存中。JS 引擎为变量“greet”分配了“undefined”值。
- 在执行期间(执行上下文 - 执行阶段),函数对象是动态创建的(尚未执行),被分配给“greet”变量,并且可以使用“greet('somename')'调用它。

3. Immediately Invoked Funtion Expression:

3. 立即调用函数表达式:

Example:

例子:

// IIFE
var greeting = function(name) {
    return 'Namaste' + ' ' + name;
}('Santosh')

console.log(greeting)  // Namaste Santosh. 

How IIFE works:
- Notice the '()' immediately after the function declaration. Every funtion object has a 'CODE' property attached to it which is callable. And we can call it (or invoke it) using '()' braces.
- So here, during the execution (Execution Context - Execute Phase), the function object is created and its executed at the same time- So now, the greeting variable, instead of having the funtion object, has its return value ( a string )

IIFE 的工作原理
- 注意函数声明之后的“()”。每个功能对象都有一个可调用的“CODE”属性。我们可以使用 '()' 大括号调用它(或调用它)。
- 所以在这里,在执行期间(执行上下文 - 执行阶段),函数对象被创建并同时执行- 所以现在,greeting 变量,而不是函数对象,有它的返回值(一个字符串)

Typical usecase of IIFE in JS:

IIFE 在 JS 中的典型用例:

The following IIFE pattern is quite commonly used.

以下 IIFE 模式非常常用。

// IIFE 
// Spelling of Function was not correct , result into error
(function (name) {
   var greeting = 'Namaste';
   console.log(greeting + ' ' + name);
})('Santosh');
  • we are doing two things over here. a) Wrapping our function expression inside braces (). This goes to tell the syntax parser the whatever placed inside the () is an expression (function expression in this case) and is a valid code.
    b) We are invoking this funtion at the same time using the () at the end of it.
  • 我们在这里做两件事。a) 将我们的函数表达式包裹在大括号 () 中。这将告诉语法解析器放在 () 中的任何内容都是一个表达式(在本例中为函数表达式)并且是一个有效的代码。
    b) 我们同时使用函数末尾的 () 来调用该函数。

So this function gets created and executed at the same time (IIFE).

所以这个函数同时被创建和执行(IIFE)。

Important usecase for IIFE:

IIFE 的重要用例:

IIFE keeps our code safe.
- IIFE, being a function, has its own execution context, meaning all the variables created inside it are local to this function and are not shared with the global execution context.

IIFE 确保我们的代码安全。
- IIFE 作为一个函数,有它自己的执行上下文,这意味着它内部创建的所有变量都是该函数的本地变量,不与全局执行上下文共享。

Suppose I've another JS file (test1.js) used in my applicaiton along with iife.js (see below).

假设我的应用程序中使用了另一个 JS 文件 (test1.js) 和 iife.js(见下文)。

// test1.js

var greeting = 'Hello';

// iife.js
// Spelling of Function was not correct , result into error
(function (name) { 
   var greeting = 'Namaste';
   console.log(greeting + ' ' + name);
})('Santosh');

console.log(greeting)   // No collision happens here. It prints 'Hello'.

So IIFE helps us to write safe code where we are not colliding with the global objects unintentionally.

因此 IIFE 可以帮助我们编写安全的代码,避免无意中与全局对象发生冲突。

回答by James Hill

That is a self-invoking anonymous function.

那是一个自调用匿名函数

Check out the W3Schools explanation of a self-invoking function.

查看W3Schools 对自调用函数的解释

Function expressions can be made "self-invoking".

A self-invoking expression is invoked (started) automatically, without being called.

Function expressions will execute automatically if the expression is followed by ().

You cannot self-invoke a function declaration.

可以使函数表达式“自调用”。

自调用表达式会自动调用(启动),而不会被调用。

如果表达式后跟 (),函数表达式将自动执行。

您不能自调用函数声明。