520 Stimmen

Was ist der Zweck einer selbstausführenden Funktion in Javascript?

In javascript, wann würden Sie dies verwenden möchten:

(function(){
    //Bunch of code...
})();

darüber:

//Bunch of code...

494voto

Ken Browning Punkte 27913

Alles dreht sich um variables Scoping. Variablen, die in der selbstausführenden Funktion deklariert werden, sind standardmäßig nur für den Code innerhalb der selbstausführenden Funktion verfügbar. So kann Code geschrieben werden, ohne dass es darauf ankommt, wie Variablen in anderen Blöcken von JavaScript-Code benannt werden.

Zum Beispiel, wie in einem Kommentar von Alexander :

(function() {
  var foo = 3;
  console.log(foo);
})();

console.log(foo);

Dies wird zunächst protokolliert 3 und werfen dann einen Fehler bei der nächsten console.log denn foo ist nicht definiert.

137voto

Sean Holden Punkte 1189

Vereinfacht. Es sieht so normal aus, dass es fast tröstlich ist:

var userName = "Sean";

console.log(name());

function name() {
  return userName;
}

Was aber, wenn ich eine wirklich praktische Javascript-Bibliothek in meine Seite einfüge, die fortgeschrittene Zeichen in ihre Basisrepräsentationen übersetzt?

Moment... was?

Ich meine, wenn jemand ein Zeichen mit einer Art Akzent eingibt, ich aber nur "englische" Zeichen A-Z in meinem Programm haben möchte? Nun... das spanische "ñ" und das französische "é" können in die Basiszeichen "n" und "e" übersetzt werden.

So jemand nette Person hat ein umfassendes Zeichen Konverter da draußen, dass ich in meiner Website enthalten kann geschrieben ... Ich baue ihn ein.

Ein Problem: Es gibt eine Funktion namens "Name", die mit meiner Funktion identisch ist.

Das nennt man eine Kollision. Wir haben zwei Funktionen, die in derselben Umfang mit demselben Namen. Das wollen wir vermeiden.

Wir müssen also unseren Code irgendwie einschränken.

Der einzige Weg, um Code in Javascript Umfang ist, um es in einer Funktion zu wickeln:

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter library's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

Das könnte unser Problem lösen. Alles ist jetzt eingeschlossen und kann nur von unseren öffnenden und schließenden Klammern aus erreicht werden.

Wir haben eine Funktion in einer Funktion... das ist zwar seltsam anzuschauen, aber völlig legal.

Es gibt nur ein Problem. Unser Code funktioniert nicht. Unser userName Variable wird nie in die Konsole eingegeben!

Wir können dieses Problem lösen, indem wir einen Aufruf unserer Funktion nach unserem bestehenden Codeblock hinzufügen...

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter libarary's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

main();

Oder vorher!

main();

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter libarary's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

Ein zweitrangiges Anliegen: Wie groß ist die Wahrscheinlichkeit, dass der Name "main" noch nicht verwendet wurde? ...also sehr, sehr gering.

Wir brauchen MEHR Scoping. Und eine Möglichkeit, unsere main()-Funktion automatisch auszuführen.

Nun kommen wir zu den selbstausführenden Funktionen (oder selbstausführenden, selbstlaufenden, was auch immer).

((){})();

Die Syntax ist sündhaft kompliziert. Aber es funktioniert.

Wenn Sie eine Funktionsdefinition in Klammern einschließen und eine Parameterliste (eine weitere Reihe von Klammern!) hinzufügen, wirkt sie wie eine Funktion aufrufen .

Schauen wir uns also unseren Code noch einmal an, mit einer selbstausführenden Syntax:

(function main() {
  var userName = "Sean";

    console.log(name());

    function name() {
      return userName;
    }
  }
)();

In den meisten Anleitungen, die Sie lesen, werden Sie nun mit dem Begriff "anonymous self-executing" oder etwas Ähnlichem bombardiert.

Nach vielen Jahren der beruflichen Entwicklung habe ich stark fordern Sie auf, zu benennen jede Funktion, die Sie schreiben für Debugging-Zwecke.

Wenn etwas schief geht (und das wird es), werden Sie den Backtrace in Ihrem Browser überprüfen. Das ist immer Es ist einfacher, Ihre Code-Probleme einzugrenzen, wenn die Einträge im Stack-Trace Namen haben!

Sehr langatmig, aber ich hoffe, es hilft!

33voto

M A Hossain Tonu Punkte 1397

Selbsteinberufung (auch bekannt als Auto-Invokation) ist, wenn eine Funktion unmittelbar nach ihrer Definition ausgeführt wird. Dies ist ein Kernmuster und dient als Grundlage für viele andere Muster von JavaScript Entwicklung.

Ich bin ein großer Fan :) von ihr, weil:

  • Es reduziert den Code auf ein Minimum
  • Es erzwingt die Trennung von Verhalten und Darstellung
  • Sie bietet einen Abschluss, der Benennungskonflikte verhindert

Enorm - (Warum sollten Sie sagen, dass es gut ist?)

  • Es geht darum, eine Funktion auf einmal zu definieren und auszuführen.
  • Sie könnten diese selbstausführende Funktion einen Wert zurückgeben lassen und die Funktion als Parameter an eine andere Funktion übergeben.
  • Es ist gut für die Einkapselung.
  • Es ist auch gut für das Block-Scoping.
  • Ja, Sie können alle Ihre .js-Dateien in eine selbstausführende Funktion einschließen und so eine globale Namespace-Verschmutzung verhindern ;)

Mehr aquí .

21voto

Christoph Punkte 157217

Namespacing. Die Geltungsbereiche von JavaScript sind auf Funktionsebene.

14voto

David W. Keith Punkte 2226

Ich kann nicht glauben, dass in keiner der Antworten implizite Globals erwähnt werden.

El (function(){})() Konstrukt schützt nicht vor impliziten Globals, was für mich die größere Sorge ist, siehe http://yuiblog.com/blog/2006/06/01/global-domination/

Grundsätzlich stellt der Funktionsblock sicher, dass alle abhängigen "globalen Variablen", die Sie definiert haben, auf Ihr Programm beschränkt sind; er schützt Sie nicht davor, implizite globale Variablen zu definieren. JSHint oder ähnliches können Empfehlungen geben, wie man sich gegen dieses Verhalten schützen kann.

Je prägnanter var App = {} Syntax bietet ein ähnliches Maß an Schutz und kann in den Funktionsblock eingeschlossen werden, wenn es sich um "öffentliche" Seiten handelt. (siehe Ember.js o SproutCore für Beispiele aus der Praxis von Bibliotheken, die dieses Konstrukt verwenden)

Soweit private Eigenschaften gehen, sind sie irgendwie überbewertet, es sei denn, Sie sind die Schaffung eines öffentlichen Rahmens oder einer Bibliothek, aber wenn Sie sie zu implementieren müssen, Douglas Crockford hat einige gute Ideen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X