Erklären Sie die Syntax der gekapselten anonymen Funktion

Lesezeit: 9 Minuten

Erklaren Sie die Syntax der gekapselten anonymen Funktion
Prem

Zusammenfassung

Können Sie die Argumentation hinter der Syntax für gekapselte anonyme Funktionen in JavaScript erklären? Warum funktioniert das: (function(){})(); aber das geht nicht: function(){}();?


Was ich weiß

In JavaScript erstellt man eine benannte Funktion wie folgt:

function twoPlusTwo(){
    alert(2 + 2);
}
twoPlusTwo();

Sie können auch eine anonyme Funktion erstellen und einer Variablen zuweisen:

var twoPlusTwo = function(){
    alert(2 + 2);
};
twoPlusTwo();

Sie können einen Codeblock kapseln, indem Sie eine anonyme Funktion erstellen, sie dann in Klammern setzen und sofort ausführen:

(function(){
    alert(2 + 2);
})();

Dies ist nützlich, wenn Sie modularisierte Skripte erstellen, um zu vermeiden, dass der aktuelle Bereich oder der globale Bereich mit möglicherweise widersprüchlichen Variablen überladen wird – wie im Fall von Greasemonkey-Skripten, jQuery-Plug-ins usw.

Jetzt verstehe ich, warum das funktioniert. Die Klammern schließen den Inhalt ein und zeigen nur das Ergebnis (ich bin sicher, dass es eine bessere Art gibt, das zu beschreiben), wie zum Beispiel with (2 + 2) === 4.


Was ich nicht verstehe

Aber ich verstehe nicht, warum das nicht genauso gut funktioniert:

function(){
    alert(2 + 2);
}();

Kannst du mir das erklären?

  • Ich denke, all diese unterschiedlichen Notationen und Möglichkeiten zum Definieren/Festlegen/Aufrufen von Funktionen sind der verwirrendste Teil der anfänglichen Arbeit mit Javascript. Die Leute neigen auch dazu, nicht darüber zu sprechen. Es ist kein hervorgehobener Punkt in Leitfäden oder Blogs. Es haut mich um, weil es für die meisten Leute etwas verwirrend ist, und Leute, die js fließend sprechen, müssen es auch durchgemacht haben. Es ist wie diese leere Tabu-Realität, über die nie gesprochen wird.

    – ahnbizcad

    29. Juni 2014 um 11:20 Uhr


  • Lesen Sie auch den Zweck dieses Konstrukts oder lesen Sie eine (technische) Erklärung (auch hier). Informationen zur Platzierung der Klammern finden Sie in dieser Frage zu ihrer Position.

    – Bergi

    16. Juli 2014 um 22:43 Uhr

  • OT: Für diejenigen, die wissen wollen, wo diese anonymen Funktionen häufig verwendet werden, lesen Sie bitte angemessen gut.com/JavaScript-Module-Pattern-In-Depth.html

    – Alireza Fattahi

    25. Februar 2015 um 7:39 Uhr


  • Dies ist ein typischer Fall von sofort aufgerufenen Funktionsausdrücken (IIFE).

    – Aminu Kano

    21. August 2018 um 6:16 Uhr

1646708114 657 Erklaren Sie die Syntax der gekapselten anonymen Funktion
Christian C. Salvado

Es funktioniert nicht, weil es als analysiert wird FunctionDeclarationund der Namensbezeichner von Funktionsdeklarationen ist verpflichtend.

Wenn Sie es in Klammern einschließen, wird es als ausgewertet FunctionExpressionund Funktionsausdrücke können benannt werden oder nicht.

Die Grammatik eines FunctionDeclaration sieht aus wie das:

function Identifier ( FormalParameterListopt ) { FunctionBody }

Und FunctionExpressionS:

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

Wie Sie sehen können Identifier (Kennungopt) Token ein FunctionExpression ist optional, daher können wir einen Funktionsausdruck ohne definierten Namen haben:

(function () {
    alert(2 + 2);
}());

Oder genannt Funktionsausdruck:

(function foo() {
    alert(2 + 2);
}());

Die Klammern (formal als der Gruppierungsoperator) können nur Ausdrücke umgeben, und ein Funktionsausdruck wird ausgewertet.

Die beiden Grammatikproduktionen können mehrdeutig sein und genau gleich aussehen, zum Beispiel:

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

Der Parser weiß, ob es sich um eine FunctionDeclaration oder ein FunctionExpressionabhängig von Kontext wo es erscheint.

Im obigen Beispiel ist der zweite ein Ausdruck, weil die Komma-Operator kann auch nur Ausdrücke verarbeiten.

Andererseits, FunctionDeclarations könnten eigentlich nur in sogenannten “Program” Code, d. h. Code außerhalb des globalen Geltungsbereichs und innerhalb des FunctionBody von anderen Funktionen.

Funktionen innerhalb von Blöcken sollten vermieden werden, da sie zu einem unvorhersehbaren Verhalten führen können, z.

if (true) {
  function foo() {
    alert('true');
  }
} else {
  function foo() {
    alert('false!');
  }
}

foo(); // true? false? why?

Der obige Code sollte eigentlich a erzeugen SyntaxErrorseit einem Block kann nur Anweisungen enthalten (und die ECMAScript-Spezifikation definiert keine Funktionsanweisungen), aber die meisten Implementierungen sind tolerant und nehmen einfach die zweite Funktion, diejenige, die warnt 'false!'.

Die Mozilla-Implementierungen – Rhino, SpiderMonkey – haben ein anderes Verhalten. Ihre Grammatik enthält a nicht standardmäßig Function Statement, was bedeutet, dass die Funktion ausgewertet wird Laufzeitnicht zur Parse-Zeit, wie es bei passiert FunctionDeclarationS. In diesen Implementierungen erhalten wir die erste definierte Funktion.


Funktionen können auf verschiedene Arten deklariert werden, vergleiche folgendes:

1- Eine mit definierte Funktion Funktion Konstruktor, der der Variablen zugewiesen ist multiplizieren:

var multiply = new Function("x", "y", "return x * y;");

2- Eine Funktionsdeklaration einer benannten Funktion multiplizieren:

function multiply(x, y) {
    return x * y;
}

3- Ein der Variablen zugewiesener Funktionsausdruck multiplizieren:

var multiply = function (x, y) {
    return x * y;
};

4- Ein benannter Funktionsausdruck Funktionsnameder Variablen zugewiesen multiplizieren:

var multiply = function func_name(x, y) {
    return x * y;
};

  • Die Antwort von CMS ist richtig. Eine hervorragende ausführliche Erläuterung von Funktionsdeklarationen und -ausdrücken finden Sie unter dieser Artikel von kangax.

    – Tim unten

    27. Oktober 2009 um 23:41 Uhr


  • Dies ist eine großartige Antwort. Es scheint eng damit verbunden zu sein, wie der Quelltext geparst wird – und mit der Struktur der BNF. Soll ich in Ihrem Beispiel 3 sagen, dass es sich um einen Funktionsausdruck handelt, weil er auf ein Gleichheitszeichen folgt, während dieses Formular eine Funktionsdeklaration / -anweisung ist, wenn es in einer eigenen Zeile erscheint? Ich frage mich, was der Zweck davon wäre – wird es nur als benannte Funktionsdeklaration interpretiert, aber ohne Namen? Welchem ​​Zweck dient das, wenn Sie es nicht einer Variablen zuweisen, benennen oder aufrufen?

    – Bretonisch

    27. Oktober 2009 um 23:50 Uhr

  • Aha. Sehr hilfreich. Danke CMS. Dieser Teil der Mozilla-Dokumentation, auf den Sie verlinkt haben, ist besonders aufschlussreich: developer.mozilla.org/En/Core_JavaScript_1.5_Reference/…

    – Früh

    27. Oktober 2009 um 23:57 Uhr

  • +1, obwohl Sie die schließende Klammer im Funktionsausdruck an der falschen Position hatten 🙂

    – NickFitz

    28. Oktober 2009 um 10:33 Uhr

  • @GovindRai, Nein. Funktionsdeklarationen werden zur Kompilierzeit behandelt und eine doppelte Funktionsdeklaration überschreibt die vorherige Deklaration. Zur Laufzeit ist die Funktionsdeklaration bereits verfügbar und in diesem Fall ist diejenige verfügbar, die “false” warnt. Weitere Informationen finden Sie unter Du kennst JS nicht

    – Saurabh Misra

    7. März 2018 um 10:29 Uhr

Auch wenn dies eine alte Frage und Antwort ist, behandelt sie ein Thema, das bis heute viele Entwickler aus der Fassung bringt. Ich kann die Zahl der JavaScript-Entwicklerkandidaten, die ich interviewt habe, nicht zählen, die mir den Unterschied zwischen einer Funktionsdeklaration und einem Funktionsausdruck nicht erklären konnten und der keine Ahnung hatte, was ein sofort aufgerufener Funktionsausdruck ist.

Ich möchte jedoch eine sehr wichtige Sache erwähnen, nämlich dass Premasagars Codeschnipsel nicht funktionieren würde, selbst wenn er ihm einen Namensbezeichner gegeben hätte.

function someName() {
    alert(2 + 2);
}();

Der Grund, warum dies nicht funktionieren würde, ist, dass die JavaScript-Engine dies als eine Funktionsdeklaration interpretiert, gefolgt von einem völlig unabhängigen Gruppierungsoperator, der keinen Ausdruck und Gruppierungsoperatoren enthält Muss einen Ausdruck enthalten. Laut JavaScript entspricht das obige Code-Snippet dem folgenden.

function someName() {
    alert(2 + 2);
}

();

Eine andere Sache, auf die ich hinweisen möchte und die für einige Leute von Nutzen sein könnte, ist, dass jede Namenskennung, die Sie für einen Funktionsausdruck angeben, im Kontext des Codes ziemlich nutzlos ist, außer innerhalb der Funktionsdefinition selbst.

var a = function b() {
    // do something
};
a(); // works
b(); // doesn't work

var c = function d() {
    window.setTimeout(d, 1000); // works
};

Natürlich ist die Verwendung von Namensbezeichnern mit Ihren Funktionsdefinitionen immer hilfreich, wenn es um das Debuggen von Code geht, aber das ist etwas ganz anderes … 🙂

Es wurden bereits tolle Antworten gepostet. Ich möchte jedoch darauf hinweisen, dass Funktionsdeklarationen einen leeren Abschlussdatensatz zurückgeben:

14.1.20 – Laufzeitsemantik: Auswertung

Funktionsdeklaration : function BindingIdentifier ( FormaleParameter ) { FunctionBody }

  1. Zurückkehren Normaler Abschluss(leer).

Diese Tatsache ist nicht leicht zu beobachten, da die meisten Versuche, den zurückgegebenen Wert zu erhalten, die Funktionsdeklaration in einen Funktionsausdruck umwandeln. Aber, eval zeigt es:

var r = eval("function f(){}");
console.log(r); // undefined

Der Aufruf eines leeren Abschlussprotokolls macht keinen Sinn. Deshalb function f(){}() kann nicht funktionieren. Tatsächlich versucht die JS-Engine nicht einmal, es aufzurufen, die Klammern werden als Teil einer anderen Anweisung betrachtet.

Aber wenn Sie die Funktion in Klammern setzen, wird sie zu einem Funktionsausdruck:

var r = eval("(function f(){})");
console.log(r); // function f(){}

Funktionsausdrücke geben ein Funktionsobjekt zurück. Und deshalb kann man es nennen: (function f(){})().

  • Schade, dass diese Antwort übersehen wird. Obwohl es nicht so umfassend ist wie die akzeptierte Antwort, bietet es einige sehr nützliche zusätzliche Informationen und verdient mehr Stimmen

    – Avrohom Jisroel

    18. Juli 2017 um 13:02 Uhr

Erklaren Sie die Syntax der gekapselten anonymen Funktion
asmmamud

In Javascript heißt das Sofort aufgerufener Funktionsausdruck (IIFE) .

Um daraus einen Funktionsausdruck zu machen, müssen Sie:

  1. schließen Sie es mit ()

  2. Platzieren Sie einen void-Operator davor

  3. weise es einer Variablen zu.

Andernfalls wird es als Funktionsdefinition behandelt und Sie können es nicht gleichzeitig auf folgende Weise aufrufen/aufrufen:

 function (arg1) { console.log(arg1) }(); 

Das obige wird Ihnen Fehler geben. Denn Sie können einen Funktionsausdruck nur sofort aufrufen.

Dies kann auf verschiedene Arten erreicht werden: Methode 1:

(function(arg1, arg2){
//some code
})(var1, var2);

Weg 2:

(function(arg1, arg2){
//some code
}(var1, var2));

Weg 3:

void function(arg1, arg2){
//some code
}(var1, var2);

Weg 4:

  var ll = function (arg1, arg2) {
      console.log(arg1, arg2);
  }(var1, var2);

Alles oben wird sofort den Funktionsausdruck aufrufen.

Ich habe noch eine kleine Anmerkung. Ihr Code funktioniert mit einer kleinen Änderung:

var x = function(){
    alert(2 + 2);
}();

Ich verwende die obige Syntax anstelle der weiter verbreiteten Version:

var module = (function(){
    alert(2 + 2);
})();

weil ich es nicht geschafft habe, dass die Einrückung für Javascript-Dateien in vim korrekt funktioniert. Es scheint, dass vim die geschweiften Klammern in offenen Klammern nicht mag.

  • Warum funktioniert diese Syntax also, wenn Sie das ausgeführte Ergebnis einer Variablen zuweisen, aber nicht eigenständig?

    – calebds

    16. Juli 2012 um 20:54 Uhr


  • @paislee – Weil die JavaScript-Engine jede gültige JavaScript-Anweisung interpretiert, die mit beginnt function Stichwort als Funktionsdeklaration in diesem Fall der Nachlauf () wird interpretiert als ein Gruppierungsoperator was nach JavaScript-Syntaxregeln nur und kann Muss einen JavaScript-Ausdruck enthalten.

    – natlee75

    26. August 2012 um 4:06 Uhr

  • @bosonix – Ihre bevorzugte Syntax funktioniert gut, aber es ist eine gute Idee, entweder die “weiter verbreitete Version”, auf die Sie verwiesen haben, oder die Variante wo zu verwenden () ist aus Gründen der Konsistenz in den Gruppierungsoperator eingeschlossen (der von Douglas Crockford dringend empfohlen wird): Es ist üblich, IIFEs zu verwenden, ohne sie einer Variablen zuzuweisen, und es ist leicht zu vergessen, diese umschließenden Klammern einzuschließen, wenn Sie sie nicht konsequent verwenden.

    – natlee75

    26. August 2012 um 4:08 Uhr

1646708115 162 Erklaren Sie die Syntax der gekapselten anonymen Funktion
Barmar

(function(){
     alert(2 + 2);
 })();

Die obige Syntax ist gültig, da alles, was in Klammern übergeben wird, als Funktionsausdruck betrachtet wird.

function(){
    alert(2 + 2);
}();

Oben ist keine gültige Syntax. Da der Java-Script-Syntax-Parser nach dem Funktionsschlüsselwort nach dem Funktionsnamen sucht, da er nichts findet, gibt er einen Fehler aus.

  • Warum funktioniert diese Syntax also, wenn Sie das ausgeführte Ergebnis einer Variablen zuweisen, aber nicht eigenständig?

    – calebds

    16. Juli 2012 um 20:54 Uhr


  • @paislee – Weil die JavaScript-Engine jede gültige JavaScript-Anweisung interpretiert, die mit beginnt function Stichwort als Funktionsdeklaration in diesem Fall der Nachlauf () wird interpretiert als ein Gruppierungsoperator was nach JavaScript-Syntaxregeln nur und kann Muss einen JavaScript-Ausdruck enthalten.

    – natlee75

    26. August 2012 um 4:06 Uhr

  • @bosonix – Ihre bevorzugte Syntax funktioniert gut, aber es ist eine gute Idee, entweder die “weiter verbreitete Version”, auf die Sie verwiesen haben, oder die Variante wo zu verwenden () ist aus Gründen der Konsistenz in den Gruppierungsoperator eingeschlossen (der von Douglas Crockford dringend empfohlen wird): Es ist üblich, IIFEs zu verwenden, ohne sie einer Variablen zuzuweisen, und es ist leicht zu vergessen, diese umschließenden Klammern einzuschließen, wenn Sie sie nicht konsequent verwenden.

    – natlee75

    26. August 2012 um 4:08 Uhr

Vielleicht wäre das die kürzere Antwort

function() { alert( 2 + 2 ); }

ist ein Funktionsliteral das definiert eine (anonyme) Funktion. Auf oberster Ebene wird kein zusätzliches ()-Paar erwartet, das als Ausdruck interpretiert wird, sondern nur Literale.

(function() { alert( 2 + 2 ); })();

ist in einem Ausdrucksanweisung das ruft eine anonyme Funktion.

971450cookie-checkErklären Sie die Syntax der gekapselten anonymen Funktion

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy