it-swarm.com.de

Was bedeuten Klammern um eine Objekt- / Funktions- / Klassendeklaration?

Ich bin neu in JavaScript und YUI . In Beispielen für YUI-Bibliotheken finden Sie viele Verwendungen dieses Konstrukts:

(function() {
    var Dom = YAHOO.util.Dom,
    Event = YAHOO.util.Event,
    layout = null,
        ...
})();

Ich denke, die letzten paar Klammern sollen die Funktion direkt nach der Deklaration ausführen.

... Aber was ist mit den vorherigen Klammern, die die Funktionsdeklaration umgeben?

Ich denke, es ist eine Frage des Umfangs. Das ist, um innere Variablen vor äußeren Funktionen und möglicherweise globalen Objekten zu verbergen. Ist es? Was ist die Mechanik dieser Klammern im Allgemeinen?

284
user54692

Es ist eine sich selbst ausführende anonyme Funktion. Der erste Satz von Klammern enthält die Ausdrücke, die ausgeführt werden sollen, und der zweite Satz von Klammern führt diese Ausdrücke aus.

Es ist ein nützliches Konstrukt, wenn Sie versuchen, Variablen aus dem übergeordneten Namespace auszublenden. Der gesamte Code innerhalb der Funktion ist im privaten Bereich der Funktion enthalten, sodass von außerhalb der Funktion überhaupt nicht auf ihn zugegriffen werden kann, sodass er wirklich privat ist.

Sehen:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

http://peter.michaux.ca/articles/javascript-namespacing

213
Andy Hume

Andy Hume so ziemlich gab die Antwort, ich möchte nur noch ein paar Details hinzufügen.

Mit diesem Konstrukt erstellen Sie eine anonyme Funktion mit einer eigenen Evaluierungsumgebung oder einem eigenen Abschluss und evaluieren sie dann sofort. Das Schöne daran ist, dass Sie auf die Variablen zugreifen können, die vor der anonymen Funktion deklariert wurden, und Sie können lokale Variablen in dieser Funktion verwenden, ohne versehentlich eine vorhandene zu überschreiben Variable.

Die Verwendung des var Schlüsselworts ist sehr wichtig, da in JavaScript jede Variable standardmäßig global ist, Sie jedoch mit dem Schlüsselwort ein neues lexikalisches Schlüsselwort erstellen Variable , das heißt, sie wird durch den Code zwischen den beiden geschweiften Klammern angezeigt. In Ihrem Beispiel erstellen Sie im Wesentlichen kurze Aliase für die Objekte in der YUI-Bibliothek, aber es hat eine stärkere Verwendung.

Ich möchte Sie nicht ohne ein Codebeispiel zurücklassen, daher werde ich hier ein einfaches Beispiel einfügen, um einen Abschluss zu veranschaulichen:

var add_gen = function(n) {
  return function(x) {
    return n + x;
  };
};
var add2 = add_gen(2);
add2(3); // result is 5

Was geht hier vor sich? In der Funktion add_gen erstellen Sie eine weitere Funktion, die ihrem Argument einfach die Zahl n hinzufügt. Der Trick besteht darin, dass in den in der Funktionsparameterliste definierten Variablen lexikalische Variablen sind, wie die mit var definierten.

Die zurückgegebene Funktion wird zwischen den geschweiften Klammern der Funktion add_gen definiert, sodass sie Zugriff auf den Wert hat von n , auch wenn die Funktion add_gen ausgeführt wurde. Deshalb erhalten Sie 5, wenn Sie die letzte Zeile des Beispiels ausführen.

Mithilfe von lexikalisch definierten Funktionsparametern können Sie die "Probleme" umgehen, die durch die Verwendung von Schleifenvariablen in anonymen Funktionen entstehen. Nehmen Sie ein einfaches Beispiel:

for(var i=0; i<5; i++) {
  setTimeout(function(){alert(i)}, 10);
}

Das "erwartete" Ergebnis könnte die Zahl von null bis vier sein, aber Sie erhalten stattdessen vier Instanzen von fünf. Dies geschieht, weil die anonyme Funktion in setTimeout und die for-Schleife die genau gleiche i -Variable verwenden. Wenn die Funktionen ausgewertet werden, ist i 5.

Sie können das naiv erwartete Ergebnis erhalten, indem Sie die Technik in Ihrer Frage und die Tatsache verwenden, dass Funktionsparameter lexikalisch festgelegt sind. (Ich habe diesen Ansatz in einer andere Antwort )

for(var i=0; i<5; i++) {
  setTimeout(
     (function(j) {
       return function(){alert(j)};
     })(i), 10);
}

Mit der sofortigen Auswertung der äußeren Funktion erzeugen Sie in jeder Iteration eine völlig unabhängige Variable mit dem Namen j und dem aktuellen Wert von i wird in diese Variable kopiert , so dass Sie das Ergebnis erhalten, das vom ersten Versuch naiv erwartet wurde.

Ich schlage vor, dass Sie versuchen, das hervorragende Tutorial unter http://ejohn.org/apps/learn/ zu verstehen, um die Abschlüsse besser zu verstehen. Dort habe ich sehr viel gelernt.

140
bandi

... aber was ist mit den vorherigen runden Klammern, die die Funktionsdeklaration umgeben?

Insbesondere lässt es JavaScript das Konstrukt 'function () {...}' als anonymen Inline-Funktionsausdruck interpretieren. Wenn Sie die Klammern weggelassen haben:

function() {
    alert('hello');
}();

Sie würden einen Syntaxfehler erhalten, da der JS-Parser das Schlüsselwort 'function' sehen und davon ausgehen würde, dass Sie eine Funktion Anweisung der folgenden Form starten:

function doSomething() {
}

... und Sie können keine Funktionsanweisung ohne Funktionsnamen haben.

funktionsausdrücke und Funktionsanweisungen sind zwei verschiedene Konstrukte, die sehr unterschiedlich behandelt werden. Leider ist die Syntax fast identisch, so dass es nicht nur für den Programmierer verwirrend ist, auch der Parser hat Schwierigkeiten zu sagen, was Sie meinen!

46
bobince

Juts zu verfolgen, was Andy Hume und andere gesagt haben:

Das '()', das die anonyme Funktion umgibt, ist der 'Gruppierungsoperator' gemäß Definition in Abschnitt 11.1.6 der ECMA-Spezifikation: http://www.ecma-international.org/publications/files/ECMA-ST) /Ecma-262.pdf .

Wörtlich aus den Dokumenten entnommen:

11.1.6 Der Gruppierungsoperator

Die Produktion Erster Ausdruck : ( Ausdruck ) wird wie folgt bewertet:

  1. Liefert das Ergebnis der Auswertung Ausdruck. Dies kann vom Typ Referenz sein.

In diesem Zusammenhang wird die Funktion als Ausdruck behandelt.

14
user484261

Einige Überlegungen zu diesem Thema:

  • Die Klammer:

    Der Browser (Engine/Parser) ordnet die Keyword-Funktion zu

    [optional name]([optional parameters]){...code...}
    

    In einem Ausdruck wie function () {} () ergibt die letzte Klammer keinen Sinn.

    Denken Sie jetzt an

    name=function(){} ; name() !?
    

Ja, das erste Klammernpaar zwingt die anonyme Funktion, in eine Variable (gespeicherter Ausdruck) umgewandelt zu werden, und das zweite startet die Auswertung/Ausführung. Also ( function () {} ) () macht Sinn.

  • Das Dienstprogramm:?

    1. Zum Ausführen von Code beim Laden und Isolieren der verwendeten Variablen vom Rest der Seite, insbesondere wenn Namenskonflikte möglich sind.

    2. Ersetzen Sie eval ("string") durch

      (neue Funktion ("string")) ()

    3. Setzen Sie einen langen Code für den Operator "= ?:" wie folgt um:

      ergebnis = exp_to_test? (function () {... long_code ...}) (): (function () {...}) ();

6
bortunac

Die ersten Klammern beziehen sich auf die Reihenfolge der Operationen. Das 'Ergebnis' der Klammer, die die Funktionsdefinition umgibt, ist die Funktion selbst, die in der Tat die zweite Klammer ausführt.

Ich bin nicht genug von einem JavaScript-Assistenten, um eine Idee zu haben, warum es nützlich ist. : P

4
Sean Edwards

Siehe diese Frage . Der erste Satz von Klammern ist nicht erforderlich, wenn Sie einen Funktionsnamen verwenden, aber für eine namenlose Funktion ist dieses Konstrukt erforderlich. Die Klammern dienen Codierern dazu, zu erkennen, dass sie beim Durchsuchen des Codes eine selbstaufrufende Funktion anzeigen (siehe Blogger - Best-Practice-Empfehlung ).

1
palswim