简体   繁体   English

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

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

I would like to know what this means:我想知道这是什么意思:

(function () {

})();

Is this basically saying document.onload ?这基本上是在说document.onload吗?

It’s an Immediately-Invoked Function Expression, or IIFE for short. It executes immediately after it’s created.

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.

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 normal function) 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:

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

Correction suggested by 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.

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

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

It's just an anonymous function that is executed right after it's created.它只是一个匿名的 function,它在创建后立即执行。

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 ready event:这是绑定ready事件的简写形式:

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

But the above two constructs are not IIFE s.但是以上两个构造都不是IIFE

An immediately-invoked function expression (IIFE) immediately calls a function.立即调用的 function 表达式 (IIFE) 立即调用 function。 This simply means that the function is executed immediately after the completion of the definition.这仅仅意味着 function 在定义完成后立即执行。

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

That construct is called an Immediately Invoked Function Expression (IIFE) which means it gets executed immediately.该构造称为立即调用 Function 表达式 (IIFE) ,这意味着它会立即执行。 Think of it as a function getting called automatically when the interpreter reaches that function.将其视为 function 在解释器到达 function 时自动调用。

Most Common Use-case:最常见的用例:

One of its most common use cases is to limit the scope of a variable made via var .它最常见的用例之一是限制通过var生成的变量的 scope 。 Variables created via var have 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. Variables created via var have 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.

In following example, count will not be available outside the immediately invoked function ie the scope of count will not leak out of the function.在以下示例中, count在立即调用的 function 之外不可用,即count的 scope 不会从 function 泄漏。 You should get a ReferenceError , should you try to access it outside of the immediately invoked function anyway.如果您尝试在立即调用的 function 之外访问它,您应该得到一个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 let and const .在 ES6 中,我们现在可以通过letconst创建变量。 Both of them are block-scoped (unlike var which is function-scoped).它们都是块范围的(与函数范围的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.因此,您现在可以编写更简单的代码来确保变量的 scope 不会从您想要的块中泄漏出来,而不是使用 IIFE 的复杂构造来处理我上面提到的用例。

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

In this example, we used let to define count variable which makes count limited to the block of code, we created with the curly brackets {...} .在这个例子中,我们使用let来定义count变量,这使得count限制在代码块中,我们用大括号{...}创建。

I call it a “Curly Jail”.我称之为“卷曲监狱”。

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

It declares an anonymous function, then calls it:它声明了一个匿名的 function,然后调用它:

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

This is called IIFE (Immediately Invoked Function Expression).这称为 IIFE(立即调用 Function 表达式)。 One of the famous JavaScript design patterns, it is the heart and soul of the modern day Module pattern.著名的 JavaScript 设计模式之一,它是现代模块模式的核心和灵魂。 As the name suggests it executes immediately after it is created.顾名思义,它在创建后立即执行。 This pattern creates an isolated or private scope of execution.此模式创建一个隔离的或私有的 scope 执行。

JavaScript prior to ECMAScript 6 used lexical scoping, so IIFE was used for simulating block scoping. ECMAScript 6 之前的 JavaScript 使用词法作用域,因此 IIFE 用于模拟块作用域。 (With ECMAScript 6 block scoping is possible with the introduction of the let and const keywords.) Reference for issue with lexical scoping (通过引入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.使用 IIFE 的性能优势是能够通过减少 scope 查找将常用的全局对象(如windowdocument等)作为参数传递。 (Remember JavaScript looks for properties in local scope and way up the chain until global scope). (请记住 JavaScript 在本地 scope 中查找属性,然后沿着链向上直到全局范围)。 So accessing global objects in local scope reduces the lookup time like below.因此访问本地 scope 中的全局对象可以减少查找时间,如下所示。

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

This is an Immediately Invoked Function Expression in Javascript:这是在 Javascript 中立即调用的 Function 表达式:

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.示例:在 chrome 控制台中尝试以下操作。 These are expressions in JS.这些是 JS 中的表达式。
 a = 10 output = 10 (1+3) output = 4
  1. Function Expression : Function 表达式
    Example:例子:
 // Function Expression var greet = function(name){ return 'Namaste' + ' ' + name; } greet('Santosh');

How function expression works: function 表达式如何工作:
- 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. - 当 JS 引擎第一次运行时(执行上下文 - 创建阶段),这个 function(在上面 = 的右侧)不会被执行或存储在 memory 中。 Variable 'greet' is assigned 'undefined' value by the JS engine. JS 引擎为变量“greet”分配了“未定义”值。
- 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')'. - 在执行期间(执行上下文 - 执行阶段),函数 object 是动态创建的(尚未执行),分配给“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 : IIFE 的工作原理
- Notice the '()' immediately after the function declaration. - 注意紧跟在 function 声明之后的“()”。 Every funtion object has a 'CODE' property attached to it which is callable.每个函数 object 都有一个可调用的“CODE”属性。 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 ) - 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 )

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 (). a) 将我们的 function 表达式包裹在大括号 () 中。 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. b) 我们同时使用函数末尾的 () 来调用这个函数。

So this function gets created and executed at the same time (IIFE).所以这个 function 被同时创建和执行(IIFE)。

Important usecase for IIFE: IIFE 的重要用例:

IIFE keeps our code safe. IIFE 保证我们的代码安全。
- 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,作为 function,有自己的执行上下文,这意味着在其中创建的所有变量都是此 function 的本地变量,并且不与全局执行上下文共享。

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 帮助我们编写安全的代码,不会无意中与全局对象发生冲突。

No, this construct just creates a scope for naming.不,这个构造只是创建了一个 scope 用于命名。 If you break it in parts you can see that you have an external如果你把它分成几部分,你会看到你有一个外部

(...)();

That is a function invocation.那是一个 function 调用。 Inside the parenthesis you have:在括号内你有:

 function() {}

That is an anonymous function.那是一个匿名的 function。 Everything that is declared with var inside the construct will be visible only inside the same construct and will not pollute the global namespace.在构造内用var声明的所有内容都将仅在同一构造内可见,并且不会污染全局命名空间。

This is the self-invoking anonymous function.这是自调用匿名 function。 It is executed while it is defined.它在定义时执行。 Which means this function is defined and invokes itself immediate after the definition.这意味着此 function 已定义并在定义后立即调用自身。

And the explanation of the syntax is: The function within the first () parenthesis is the function which has no name and by the next ();语法的解释是:第一个()括号内的 function 是没有名称的 function 和下一个(); parenthesis you can understand that it is called at the time it is defined.括号可以理解为在定义的时候调用。 And you can pass any argument in this second () parenthesis which will be grabbed in the function which is in the first parenthesis.您可以在第二个()括号中传递任何参数,该参数将在第一个括号中的 function 中获取。 See this example:看这个例子:

 (function(obj){ // Do something with this obj })(object);

Here the 'object' you are passing will be accessible within the function by 'obj', as you are grabbing it in the function signature.在这里,您传递的“对象”将可以通过“obj”在 function 中访问,因为您在 function 签名中抓取它。

That is a self-invoking anonymous function .那是一个自调用匿名 function

Check out the W3Schools explanation of a self-invoking function .查看W3Schools 对自调用 function 的解释

Function expressions can be made "self-invoking". Function 表达式可以“自调用”。

A self-invoking expression is invoked (started) automatically, without being called.自调用表达式被自动调用(启动),而不被调用。

Function expressions will execute automatically if the expression is followed by (). Function 表达式如果后跟 () 将自动执行。

You cannot self-invoke a function declaration.您不能自行调用 function 声明。

Start here:从这里开始:

 var b = 'bee'; console.log(b); // global

Put it in a function and it is no longer global -- your primary goal.把它放在 function 中,它不再是全球性的——你的主要目标。

 function a() { var b = 'bee'; console.log(b); } a(); console.log(b); // ReferenceError: b is not defined -- *as desired*

Call the function immediately -- oops:立即致电 function -- 哎呀:

 function a() { var b = 'bee'; console.log(b); }(); // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'

Use the parentheses to avoid a syntax error:使用括号来避免语法错误:

 (function a() { var b = 'bee'; console.log(b); })(); // OK now

You can leave off the function name:您可以省略 function 名称:

 (function () { // no name required var b = 'bee'; console.log(b); })();

It doesn't need to be any more complicated than that.它不需要比这更复杂。

It is a function expression, it stands for Immediately Invoked Function Expression (IIFE).它是一个 function 表达式,它代表立即调用的 Function 表达式 (IIFE)。 IIFE is simply a function that is executed right after it is created. IIFE 只是一个 function,它在创建后立即执行。 So insted of the function having to wait until it is called to be executed, IIFE is executed immediately.因此,由于 function 必须等到它被调用才能执行,所以 IIFE 会立即执行。 Let's construct the IIFE by example.让我们通过示例构建 IIFE。 Suppose we have an add function which takes two integers as args and returns the sum lets make the add function into an IIFE,假设我们有一个 add function ,它接受两个整数作为参数并返回总和,让我们将 function 添加到 IIFE 中,

Step 1: Define the function步骤 1:定义 function

 function add (a, b){ return a+b; } add(5,5);

Step2: Call the function by wrap the entire functtion declaration into parentheses Step2: 调用 function 通过将整个函数声明包装到括号中

(function add (a, b){ return a+b; }) //add(5,5);

Step 3: To invock the function immediatly just remove the 'add' text from the call.第 3 步:要立即调用 function,只需从调用中删除“添加”文本。

 (function add (a, b){ return a+b; })(5,5);

The main reason to use an IFFE is to preserve a private scope within your function.使用 IFFE 的主要原因是在 function 中保留私有 scope。 Inside your javascript code you want to make sure that, you are not overriding any global variable.在 javascript 代码中,您要确保没有覆盖任何全局变量。 Sometimes you may accidentaly define a variable that overrides a global variable.有时您可能会意外定义一个覆盖全局变量的变量。 Let's try by example.让我们举个例子。 suppose we have an html file called iffe.html and codes inside body tag are-假设我们有一个名为 iffe.html 的 html 文件,并且正文标签内的代码是-

 <body> <div id = 'demo'></div> <script> document.getElementById("demo").innerHTML = "Hello JavaScript;" </script> </body>

Well, above code will execute with out any question, now assume you decleard a variable named document accidentaly or intentional.好吧,上面的代码将毫无疑问地执行,现在假设您意外或有意地清除了一个名为 document 的变量。

 <body> <div id = 'demo'></div> <script> document.getElementById("demo").innerHTML = "Hello JavaScript;"; const document = "hi there". console;log(document) </script> </body>

you will endup in a SyntaxError : redeclaration of non-configurable global property document.你最终会遇到一个SyntaxError : redeclaration of non-configurable global property document。

But if your desire is to declear a variable name documet you can do it by using IFFE.但是,如果您希望清除变量名文档,您可以使用 IFFE 来实现。

 <body> <div id = 'demo'></div> <script> (function(){ const document = "hi there"; this.document.getElementById("demo").innerHTML = "Hello JavaScript;". console;log(document); })(). document.getElementById("demo");innerHTML = "Hello JavaScript " </script> </body>

Output: Output:

在此处输入图像描述

Let's try by an another example, suppose we have an calculator object like bellow-让我们再举一个例子,假设我们有一个计算器 object,如下所示——

 <body> <script> var calculator = { add:function(a,b){ return a+b; }, mul:function(a,b){ return a*b; } } console.log(calculator.add(5,10)); </script> </body>

Well it's working like a charm, what if we accidently re-assigne the value of calculator object.好吧,它就像一个魅力,如果我们不小心重新分配了计算器 object 的值怎么办。

 <body> <script> var calculator = { add:function(a,b){ return a+b; }, mul:function(a,b){ return a*b; } } console.log(calculator.add(5,10)); calculator = "scientific calculator"; console.log(calculator.mul(5,5)); </script> </body>

yes you will endup with a TypeError: calculator.mul is not a function iffe.html是的,您最终会遇到 TypeError:calculator.mul is not a function iffe.html

But with the help of IFFE we can create a private scope where we can create another variable name calculator and use it;但是在 IFFE 的帮助下,我们可以创建一个私有的 scope,我们可以在其中创建另一个变量名计算器并使用它;

 <body> <script> var calculator = { add:function(a,b){ return a+b; }, mul:function(a,b){ return a*b; } } var cal = (function(){ var calculator = { sub:function(a,b){ return ab; }, div:function(a,b){ return a/b; } } console.log(this.calculator.mul(5,10)); console.log(calculator.sub(10,5)); return calculator; })(); console.log(calculator.add(5,10)); console.log(cal.div(10,5)); </script> </body>

Output: Output: 在此处输入图像描述

Self-executing functions are typically used to encapsulate context and avoid name collusions.自执行函数通常用于封装上下文并避免名称串通。 Any variable that you define inside the (function(){..})() are not global.您在 (function(){..})() 中定义的任何变量都不是全局变量。

The code编码

var same_name = 1; var myVar = (function() { var same_name = 2; console.log(same_name); })(); console.log(same_name);

produces this output:产生这个 output:

 2 1

By using this syntax you avoid colliding with global variables declared elsewhere in your JavaScript code.通过使用这种语法,您可以避免与 JavaScript 代码中其他地方声明的全局变量发生冲突。

It is called IIFE - Immediately Invoked Function Expression.它被称为 IIFE - 立即调用 Function 表达式。 Here is an example to show it's syntax and usage.这是一个显示其语法和用法的示例。 It is used to scope the use of variables only till the function and not beyond.它用于 scope 变量的使用仅到 function 并且不超过。

 (function () { function Question(q,a,c) { this.q = q; this.a = a; this.c = c; } Question.prototype.displayQuestion = function() { console.log(this.q); for (var i = 0; i < this.a.length; i++) { console.log(i+": "+this.a[i]); } } Question.prototype.checkAnswer = function(ans) { if (ans===this.c) { console.log("correct"); } else { console.log("incorrect"); } } var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0); var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2); var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1); var questions = [q1, q2, q3]; var n = Math.floor(Math.random() * questions.length) var answer = parseInt(prompt(questions[n].displayQuestion())); questions[n].checkAnswer(answer); })();

TL;DR: Expressions can be enclosed in parenthesis, which would conflict with function calling if the expression and block forms of function were combined. TL;DR:表达式可以用括号括起来,如果将 function 的表达式和块function组合在一起,则会与 function 调用冲突。

I like counter-examples because they paint a great picture of the logic, and noone else listed any.我喜欢反例,因为它们描绘了一幅很好的逻辑图景,没有其他人列出任何东西。 You might ask, "Why can't the browser see function(){}() and just assume its an expression?"你可能会问,“为什么浏览器看不到function(){}()而只是假设它是一个表达式?” Let's juxtapose the issue with three examples.让我们将这个问题与三个例子并列。

 var x; // Here, fibonacci is a block function function fibonacci(x) { var value = x < 2? x: fibonacci(x-1) + fibonacci(x-2); if (x === 9) console.log("The " + x + "th fibonacci is: " + value); return value; } (x = 9); console.log("Value of x: " + x); console.log("fibonacci is a(n) " + typeof fibonacci);

Observe how things change when we turn the function into an expression.观察当我们将 function 转换为表达式时情况如何变化。

 var x; // Here, fibonacci is a function expression (function fibonacci(x) { var value = x < 2? x: fibonacci(x-1) + fibonacci(x-2); if (x === 9) console.log("The " + x + "th fibonacci is: " + value); return value; }) (x = 9); console.log("Value of x: " + x); console.log("fibonacci is a(n) " + typeof fibonacci);

The same thing happens when you use the not-operator instead of parenthesis because both operators turn the statement into an expression:当您使用非运算符而不是括号时,也会发生同样的事情,因为两个运算符都将语句转换为表达式:

 var x; // Here, fibonacci is a function expression? function fibonacci(x) { var value = x < 2: x; fibonacci(x-1) + fibonacci(x-2). if (x === 9) console:log("The " + x + "th fibonacci is; " + value); return value; } (x = 9). console:log("Value of x; " + x). console;log("fibonacci is a(n) " + typeof fibonacci)

By turning the function into an expression, it gets executed by the (x = 9) two lines down from it.通过将 function 转换为表达式,它由(x = 9)下两行执行。 Thanks to separate behaviors for expression functions and block functions, both examples run fine without ambiguity (specs-wise).由于表达式函数和块函数的不同行为,两个示例都运行良好,没有歧义(规范方面)。

Name Scoping名称范围

Another important observation is that named block functions are visible to the entire scope, whereas function expressions are only visible to themselves.另一个重要的观察是命名块函数对整个 scope 可见,而 function 表达式只对它们自己可见。 In other words, fibonacci is only visible to the last console.log when it is a block in the first example.换句话说, fibonacci只有在第一个示例中是块时才对最后一个console.log可见。 In all three examples, fibonacci is visible to itself, allowing fibonacci to call itself, which is recursion.在所有三个示例中, fibonacci对自身都是可见的,允许fibonacci调用自身,这就是递归。

Arrow Functions箭头函数

Another aspect to the logic is arrow functions.逻辑的另一个方面是箭头函数。 The specs would have had to include arbitrary rules and exceptions for arrow functions if the definitions of block and expression functions were merged together:如果将块函数和表达式函数的定义合并在一起,则规范必须包含箭头函数的任意规则和例外:

 function hello() {console.log("Hello World")} (x) => console.log("hello " + x) console.log("If you are reading this, no errors occurred");

Although function blocks work fine, function expressions followed by an arrow function produce a syntax error:尽管 function 块工作正常,但 function 表达式后跟箭头 function 会产生语法错误:

 . function hello() {console.log("Hello World")} (x) => console.log("hello " + x) console,log("If you are reading this; no errors occurred")

Here, it is ambiguous whether the (x) on line two is calling the function on the preceding line or whether it is the function arguments for an arrow function. Here, it is ambiguous whether the (x) on line two is calling the function on the preceding line or whether it is the function arguments for an arrow function.

Note that arrow functions have been indeed to the ECMAScript standard over the years and were not a factor in the initial design of the language;请注意,箭头函数多年来确实符合 ECMAScript 标准,并且在语言的初始设计中并不是一个因素; my point is that a differentiation between expression and block functions helps JavaScript syntax to be a little more logical and coherent.我的观点是,表达式和块函数之间的区别有助于 JavaScript 语法更加合乎逻辑和连贯。

Self-executing anonymous function.自执行匿名 function。 It's executed as soon as it is created.它在创建后立即执行。

One short and dummy example where this is useful is:一个有用的简短示例是:

 function prepareList(el){ var list = (function(){ var l = []; for(var i = 0; i < 9; i++){ l.push(i); } return l; })(); return function (el){ for(var i = 0, l = list.length; i < l; i++){ if(list[i] == el) return list[i]; } return null; }; } var search = prepareList(); search(2); search(3);

So instead of creating a list each time, you create it only once (less overhead).因此,不是每次都创建一个列表,而是只创建一次(开销更少)。

One more use case is memoization where a cache object is not global:另一个用例是缓存 object 不是全局的记忆化:

 var calculate = (function() { var cache = {}; return function(a) { if (cache[a]) { return cache[a]; } else { // Calculate heavy operation cache[a] = heavyOperation(a); return cache[a]; } } })();

IIFE (Immediately invoked function expression) is a function which executes as soon as the script loads and goes away. IIFE(立即调用 function 表达式)是一个 function,它在脚本加载并消失后立即执行。

Consider the function below written in a file named iife.js考虑下面写在名为 iife.js 的文件中的 function

 (function(){ console.log("Hello Stackoverflow;"); })()

This code above will execute as soon as you load iife.js and will print ' Hello Stackoverflow ' on the developer tools' console.上面的代码将在您加载 iife.js 后立即执行,并将在开发人员工具的控制台上打印“ Hello Stackoverflow ”。

For a Detailed explanation see Immediately-Invoked Function Expression (IIFE)有关详细说明,请参阅立即调用 Function 表达式 (IIFE)

The following code:以下代码:

 (function () { })();

is called an immediately invoked function expression (IIFE).被称为立即调用的 function 表达式(IIFE)。

It is called a function expression because the ( yourcode ) operator in Javascript force it into an expression.它被称为 function 表达式,因为( yourcode )运算符将其强制转换为表达式。 The difference between a function expression and a function declaration is the following: function 表达式function 声明之间的区别如下:

 // declaration: function declaredFunction () {} // expressions: // storing function into variable const expressedFunction = function () {} // Using () operator, which transforms the function into an expression (function () {})

An expression is simply a bunch of code which can be evaluated to a single value .表达式只是一堆可以计算为单个值的代码。 In case of the expressions in the above example this value was a single function object .对于上述示例中的表达式,此值为单个 function object

After we have an expression which evaluates to a function object we then can immediately invoke the function object with the () operator.在我们有一个计算结果为 function object 的表达式之后,我们可以立即使用 6 ()运算符调用function ZA8CFDE6666。 For example:例如:

 (function() { const foo = 10; // all variables inside here are scoped to the function block console.log(foo); })(); console.log(foo); // referenceError foo is scoped to the IIFE

Why is this useful?为什么这很有用?

When we are dealing with a large code base and/or when we are importing various libraries the chance of naming conflicts increases.当我们处理大型代码库和/或导入各种库时,命名冲突的可能性会增加。 When we are writing certain parts of our code which is related (and thus is using the same variables) inside an IIFE all of the variables and function names are scoped to the function brackets of the IIFE .当我们在 IIFE 中编写与(因此使用相同变量)相关的代码的某些部分时,所有变量和 function 名称的范围都在 IIFE 的 function 括号内 This reduces chances of naming conflicts and lets you name them more careless (eg you don't have to prefix them).这减少了命名冲突的机会,并且让您可以更粗心地命名它们(例如,您不必为它们加上前缀)。

This function is called self-invoking function.这个 function 称为自调用 function。 A self-invoking (also called self-executing) function is a nameless (anonymous) function that is invoked(Called) immediately after its definition.自调用(也称为自执行)function 是一个无名(匿名)function,在其定义后立即调用(调用)。 Read more here 在这里阅读更多

What these functions do is that when the function is defined, The function is immediately called, which saves time and extra lines of code(as compared to calling it on a seperate line).这些函数的作用是,当定义 function 时,立即调用 function,这节省了时间和额外的代码行(与在单独的行上调用它相比)。

Here is an example:这是一个例子:

 (function() { var x = 5 + 4; console.log(x); })();

Already many good answers here but here are my 2 cents:p这里已经有很多好的答案,但这是我的 2 美分:p


You can use IIFE (Immediately Invoked Function Expression) for:您可以将IIFE (立即调用 Function 表达式)用于:

  1. Avoiding pollution in the global namespace.避免全局命名空间中的污染。

    Variables defined in IIFE (or even any normal function) don't overwrite definitions in global scope. IIFE(甚至任何普通函数)中定义的变量不会覆盖全局 scope 中的定义。

  2. Protecting code from being accessed by outer code.保护代码不被外部代码访问。

    Everything that you define within the IIFE can be only be accessed within the IIFE.您在 IIFE 中定义的所有内容只能在 IIFE 中访问。 It protects code from being modified by outer code.它保护代码不被外部代码修改。 Only what you explicitly return as the result of function or set as value to outer variables is accessible by outer code.只有您作为 function 的结果显式返回或设置为外部变量的值才能被外部代码访问。

  3. Avoid naming functions that you don't need to use repeatedly.避免命名不需要重复使用的函数。 Though it's possible to use a named function in IIFE pattern you don't do it as there is no need to call it repeatedly, generally.虽然可以在 IIFE 模式中使用名为 function 的名称,但您不必这样做,因为通常不需要重复调​​用它。

  4. For Universal Module Definitions which is used in many JS libraries.对于许多 JS 库中使用的通用模块定义 Check this question for details.检查此问题以获取详细信息。


IIFE is generally used in following fashion: IIFE 通常以下列方式使用:

 (function(param){ //code here })(args);

You can omit the parentheses () around anonymous function and use void operator before anonymous function.您可以省略匿名 function 周围的括号() ,并在匿名 function 之前使用void运算符。

 void function(param){ //code here }(args);

An immediately invoked function expression (IIFE) is a function that's executed as soon as it's created.立即调用的 function 表达式 (IIFE) 是一个 function,它在创建后立即执行。 It has no connection with any events or asynchronous execution.它与任何事件或异步执行无关。 You can define an IIFE as shown below:您可以定义一个 IIFE,如下所示:

 (function() { // all your code here //... })();

The first pair of parentheses function(){...} converts the code inside the parentheses into an expression.The second pair of parentheses calls the function resulting from the expression.第一对括号 function(){...} 将括号内的代码转换为表达式。第二对括号调用由表达式生成的 function。

An IIFE can also be described as a self-invoking anonymous function. IIFE也可以描述为自调用匿名 function。 Its most common usage is to limit the scope of a variable made via var or to encapsulate context to avoid name collisions.它最常见的用法是限制通过 var 生成的变量的 scope 或封装上下文以避免名称冲突。

The reason self-evoking anonymous functions are used is they should never be called by other code since they "set up" the code which IS meant to be called (along with giving scope to functions and variables).使用自诱发匿名函数的原因是它们不应该被其他代码调用,因为它们“设置”了本应被调用的代码(以及将 scope 赋予函数和变量)。

In other words, they are like programs that "make classes', at the beginning of program. After they are instantiated (automatically), the only functions that are available are the ones returned in by the anonymous function. However, all the other 'hidden' functions are still there, along with any state (variables set during scope creation).换句话说,它们就像在程序开始时“创建类”的程序。在它们被实例化(自动)之后,唯一可用的函数是匿名 function 返回的函数。但是,所有其他' hidden' 功能仍然存在,以及任何 state(在 scope 创建期间设置的变量)。

Very cool.很酷。

In ES6 syntax (posting for myself, as I keep landing on this page looking for a quick example):在 ES6 语法中(为我自己发帖,因为我一直在此页面上寻找一个快速示例):

 // simple const simpleNumber = (() => { return true? 1: 2 })() // with param const isPositiveNumber = ((number) => { return number > 0? true: false })(4)

This is a more in depth explanation of why you would use this:这是对为什么要使用它的更深入的解释:

"The primary reason to use an IIFE is to obtain data privacy. Because JavaScript's var scopes variables to their containing function, any variables declared within the IIFE cannot be accessed by the outside world." “使用 IIFE 的主要原因是为了获得数据隐私。因为 JavaScript 的 var 范围变量包含 function,所以在 IIFE 中声明的任何变量都不能被外界访问。”

http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html

JavaScript Function Syntax JavaScript 函数语法

function name(parameter1, parameter2, parameter3) {
  // code to be executed
}

The code to be executed, by the function, is placed inside curly brackets: {}函数要执行的代码放在大括号内:{}

Demo:-演示:-

let x = myFunction(4, 3);   // Function is called, return value will end up in x

function myFunction(a, b) {
  return a * b;             // Function returns the product of a and b
}
console.log(x);

output of x:- x 的输出:-

12

Same Demo without Function:-没有功能的相同演示:-

let a= 4;
let b=3;
let x = a + b;
console.log(x);

I think the 2 sets of brackets makes it a bit confusing but I saw another usage in googles example, they used something similar, I hope this will help you understand better:我认为 2 组括号让它有点混乱,但我在 google 示例中看到了另一种用法,他们使用了类似的东西,我希望这能帮助你更好地理解:

 var app = window.app || (window.app = {}); console.log(app); console.log(window.app);

so if windows.app is not defined, then window.app = {} is immediately executed, so window.app is assigned with {} during the condition evaluation, so the result is both app and window.app now become {} , so console output is: so if windows.app is not defined, then window.app = {} is immediately executed, so window.app is assigned with {} during the condition evaluation, so the result is both app and window.app now become {} , so控制台 output 是:

 Object {} Object {}

Normally, JavaScript code has global scope in the application.通常,JavaScript 代码在应用程序中具有全局 scope。 When we declare global variable in it, there is a chance for using the same duplicate variable in some other area of the development for some other purpose.当我们在其中声明全局变量时,就有机会在开发的其他领域将相同的重复变量用于其他目的。 Because of this duplication there may happen some error.由于这种重复,可能会发生一些错误。 So we can avoid this global variables by using immediately invoking function expression, this expression is self-executing expression.When we make our code inside this IIFE expression global variable will be like local scope and local variable.所以我们可以通过立即调用 function 表达式来避免这个全局变量,这个表达式是自执行表达式。当我们在这个IIFE表达式中编写代码时,全局变量将类似于局部 scope 和局部变量。

Two ways we can create IIFE我们可以通过两种方式创建IIFE

 (function () { "use strict"; var app = angular.module("myModule", []); }());

OR或者

(function () { "use strict"; var app = angular.module("myModule", []); })();

In the code snippet above, “ var app ” is a local variable now.在上面的代码片段中,“ var app ”现在是一个局部变量。

Usually, we don't invoke a function immediately after we write it in the program.通常,我们不会在将 function 写入程序后立即调用它。 In extremely simple terms, when you call a function right after its creation, it is called IIFE - a fancy name.简而言之,当您在创建 function 后立即调用它时,它被称为 IIFE - 一个花哨的名字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM