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

Exi*_*tos 739 javascript iife

我曾经知道这意味着什么,但我现在正在努力...

这基本上是说document.onload吗?

(function () {

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

gio*_*_13 812

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

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

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

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

Guffa建议的更正:

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

  • 在ES6中,可以使用箭头函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)重写上述IIFE,例如`((foo)=> foo )('foo value')`. (11认同)
  • @jlei 在我看来,js 程序的生命周期包括以下阶段:解析、创建/编译、执行。尽管实际实现(和命名 :)) )可能因浏览器而异,但我们可以通过注意解析错误、提升和运行时错误来确定代码中的这些阶段。我个人在这方面没有找到很多资源,因为它的级别太低,而且不是程序员可以控制的。您可以在此 SO 帖子中找到某种解释:http://stackoverflow.com/a/34562772/491075 (2认同)

Guf*_*ffa 107

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

这就好像你将它分配给一个变量,并在之后使用它,只是没有变量:

var f = function () {
};
f();
Run Code Online (Sandbox Code Playgroud)

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

$(function(){
});
Run Code Online (Sandbox Code Playgroud)

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

$(document).ready(function(){
});
Run Code Online (Sandbox Code Playgroud)

  • 最后两个不是真正的IIFE,因为它们在DOM准备就绪时被调用而不是*立即* (75认同)
  • @swordofpain:是的,这是正确的,他们不是IIFE. (14认同)

令狐葱*_*令狐葱 50

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

三个更常见的措辞:

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

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

!function(){}();  // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}();  // => NaN
Run Code Online (Sandbox Code Playgroud)

或者,它可以是:

~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();
Run Code Online (Sandbox Code Playgroud)

你甚至可以写:

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

  • 为什么有这么多方法写同样的东西?!! > _ <我不喜欢这种语言 (9认同)
  • aaand获胜者是`;(function(){}());` (5认同)
  • 最后一个`31.new`'是无效的语法 (4认同)

sol*_*dil 31

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

(function (local_arg) {
   // anonymous function
   console.log(local_arg);
})(arg);
Run Code Online (Sandbox Code Playgroud)


Nea*_*eal 28

那就是说立即执行.

所以,如果我这样做:

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

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


第二个例子:

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

alert(val); //18
Run Code Online (Sandbox Code Playgroud)

  • 我不明白这是什么证明它的自我调用? (2认同)

cho*_*hoc 23

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

最常见的用例:

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

在下面的示例中,count不会在立即调用的函数之外可用,即Scope count不会泄漏出函数.如果Reference Error你尝试在立即调用的函数之外访问它,你应该得到一个.

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

ES6替代品(推荐)

在ES6中,我们现在可以通过let和创建变量const.它们都是块范围的(不像var是函数作用域).

因此,代替在上面提到的用例中使用IIFE的复杂构造,您现在可以编写更多,更简单的代码,以确保变量的作用域不会泄漏出您想要的块.

{ 
    let count = 10;
};
console.log(count);  // Reference Error: count is not defined
Run Code Online (Sandbox Code Playgroud)

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

我称之为Curly Jail.

  • 我喜欢**Curly Jail**的命名.也许它会坚持:) (10认同)

Gur*_*M K 14

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

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

使用词法作用域的ECMAScript 6之前的JavaScript,IIFE用于模拟块作用域.(通过引入let和const关键字,可以使用ECMAScript 6块作用域.) 引用词法作用域的问题

使用IIFE模拟块范围

使用IIFE的性能优势是能够传递常用的全局对象,如窗口,文档等.作为一个参数,通过减少范围查找.(记住Javascript查找本地范围内的属性,然后链接到全局范围).因此,访问本地范围内的全局对象,减少查找时间,如下所示.

(function (globalObj) {
//Access the globalObj
})(window);
Run Code Online (Sandbox Code Playgroud)


Ald*_*nio 11

不,这个构造只是为命名创建了一个范围.如果你打破它的部分你可以看到你有一个外部

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

这是一个函数调用.在括号内你有:

function() {}
Run Code Online (Sandbox Code Playgroud)

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


小智 10

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

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

  1. 表达式:返回值的内容
    示例:在chrome控制台中尝试以下操作.这些是JS中的表达式.
a = 10 
output = 10 
(1+3) 
output = 4
Run Code Online (Sandbox Code Playgroud)
  1. 功能表达:
    示例:
// Function Expression 
var greet = function(name){
   return 'Namaste' + ' ' + name;
}

greet('Santosh');
Run Code Online (Sandbox Code Playgroud)

函数表达式如何工作:
- 当JS引擎第一次运行时(执行上下文 - 创建阶段),此函数(在=上面的右侧)不会被执行或存储在内存中.变量'greet'由JS引擎赋予'undefined'值.
- 在执行期间(执行上下文 - 执行阶段),功能对象即时创建(尚未执行),被分配给'greet'变量,并且可以使用'greet('somename')'调用它.

3.立即调用功能表达:

例:

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

console.log(greeting)  // Namaste Santosh. 
Run Code Online (Sandbox Code Playgroud)

IIFE如何工作:
- 在函数声明后立即注意'()'.每个funtion对象都附加一个'CODE'属性,可以调用它.我们可以使用'()'括号来调用它(或调用它).
- 所以这里,在执行(执行上下文 - 执行阶段)期间,创建函数对象并同时执行它 - 所以现在,greeting变量而不是函数对象具有其返回值(字符串)

JS中IIFE的典型用例:

以下IIFE模式是非常常用的.

// IIFE 
// Spelling of Function was not correct , result into error
(function (name) {
   var greeting = 'Namaste';
   console.log(greeting + ' ' + name);
})('Santosh');
Run Code Online (Sandbox Code Playgroud)
  • 我们在这里做了两件事.a)将我们的函数表达式包装在braces()中.这就告诉语法解析器,()中的任何内容都是表达式(在本例中为函数表达式)并且是有效代码.
    b)我们正在使用它末尾的()同时调用此函数.

因此,此功能可以同时创建和执行(IIFE).

IIFE的重要用例:

IIFE保证我们的代码安全.
- 作为一个函数的IIFE具有自己的执行上下文,这意味着在其中创建的所有变量都是该函数的本地变量,并且不与全局执行上下文共享.

假设我在我的应用程序中使用了另一个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'.
Run Code Online (Sandbox Code Playgroud)

因此,IIFE帮助我们编写安全代码,以便我们不会无意中与全局对象发生冲突.


Jam*_*ill 6

这是一个自我调用的匿名函数.

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

函数表达式可以"自我调用".

自动调用(启动)自调用表达式,而不调用.

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

您无法自行调用函数声明.

  • `(函数名为(){console.log("Hello");}());`< - 自执行*命名*函数 (3认同)
  • @RicardoGonzales递归我想 (2认同)

Md.*_*que 5

这是一个自我调用的匿名函数.它在定义时执行.这意味着定义了此函数,并在定义后立即调用.

语法的解释是:第一个()括号内的函数是没有名称的函数,通过下一个();括号,您可以理解它在定义时被调用.并且您可以在第二个()括号中传递任何参数,这些参数将在第一个括号中的函数中获取.看这个例子:

(function(obj){
    // Do something with this obj
})(object);
Run Code Online (Sandbox Code Playgroud)

这里你传递的'对象'将在函数中通过'obj'访问,因为你在函数签名中抓取它.

  • 我喜欢阅读多个答案,有时候一个或另一个的措词会产生影响. (3认同)
  • 这个问题已经有了一个已接受的答案,你的答案并没有添加任何尚未被接受答案涵盖的内容.因此,绝对没有必要写这个答案. (2认同)

Jim*_*ood 5

从这里开始:

var b = 'bee';
console.log(b);  // global
Run Code Online (Sandbox Code Playgroud)

把它放在一个函数中,它不再是全局的——你的主要目标。

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

立即调用该函数——哎呀:

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

使用括号避免语法错误:

(function a() {
  var b = 'bee';
  console.log(b);
})(); // OK now
Run Code Online (Sandbox Code Playgroud)

您可以省略函数名称:

(function () {    // no name required
  var b = 'bee';
  console.log(b);
})();
Run Code Online (Sandbox Code Playgroud)

它不需要比这更复杂。

  • 语法错误是在谈论箭头函数。据我了解,它是 js 的一个新特性,几年前它并不存在,但 IIFE 存在。所以,括号最初可能是为了避免语法错误,但不同? (2认同)

Lor*_*ord 5

It is a function expression, it stands for Immediately Invoked Function Expression (IIFE). IIFE is simply a function that is executed right after it is created. So insted of the function having to wait until it is called to be executed, IIFE is executed immediately. Let's construct the IIFE by example. Suppose we have an add function which takes two integers as args and returns the sum lets make the add function into an IIFE,

Step 1: Define the function

function add (a, b){
    return a+b;
}
add(5,5);
Run Code Online (Sandbox Code Playgroud)

Step2: Call the function by wrap the entire functtion declaration into parentheses

(function add (a, b){
    return a+b;
})
//add(5,5);
Run Code Online (Sandbox Code Playgroud)

Step 3: To invock the function immediatly just remove the 'add' text from the call.

(function add (a, b){
    return a+b;
})(5,5);
Run Code Online (Sandbox Code Playgroud)

使用 IFFE 的主要原因是在函数内保留私有范围。在您的 javascript 代码中,您需要确保没有覆盖任何全局变量。有时您可能会意外定义一个覆盖全局变量的变量。让我们通过例子来尝试一下。假设我们有一个名为iffe.html的html文件,body标签内的代码是-

<body>
    <div id = 'demo'></div>
    <script>
        document.getElementById("demo").innerHTML = "Hello JavaScript!";
    </script> 
</body>
Run Code Online (Sandbox Code Playgroud)

好吧,上面的代码将毫无问题地执行,现在假设您无意或有意地声明了一个名为 document 的变量。

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

您将最终遇到SyntaxError : redeclaration of non-configurable global property document。

但是,如果您希望声明变量名称文档,则可以使用 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>
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

让我们尝试另一个例子,假设我们有一个如下所示的计算器对象 -

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

好吧,它的工作方式就像一个魅力,如果我们不小心重新分配了计算器对象的值怎么办?

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

是的,你最终会得到一个类型错误:calculator.mul is not a function ife.html

但在 IFFE 的帮助下,我们可以创建一个私有作用域,在其中创建另一个变量名称计算器并使用它;

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

输出: 在此输入图像描述


归档时间:

查看次数:

267112 次

最近记录:

6 年,5 月 前