Einführung
In vielen traditionellen Sprachen (C/C ++/Java/C#usw.) existieren Funktionen als Bürger zweiter Klasse. Sie können nur eine Funktion mit den Schlüsselwörtern der Sprache deklarieren und sie dann aufrufen. Wenn Sie die Funktion als Parameter an eine andere Funktion übergeben oder einer lokalen Variablen oder als Rückgabewert einen Wert zuweisen müssen, müssen Sie durch spezielle Methoden wie Funktionszeiger und Proxy (Delegierter) einen Durchbruch erzielen.
In der JavaScript-Welt sind Funktionen erstklassige Bürger. Sie haben nicht nur alle Möglichkeiten, herkömmliche Funktionen (Deklarationen und Aufrufe) zu verwenden, sondern können auch Werte zuweisen, Parameter übergeben und wie einfache Werte zurückgeben. Solche Funktionen werden auch erstklassige Funktionen bezeichnet. Darüber hinaus fungieren Funktionen in JavaScript auch als Klassenkonstruktoren und sind auch Instanzen der Funktionsklasse. Solche mehreren Identitäten machen JavaScript -Funktionen sehr wichtig.
1. JavaScript-Funktion Einstiegsebene
Wie gewöhnliche Sprachen folgen auch JavaScript -Funktionen zuerst dem Prinzip der Erklärung und dann. Funktionsnamen können nur Buchstaben, Zahlen, Unterstriche oder $ enthalten und können nicht mit Zahlen beginnen. Es gibt zwei allgemeine Möglichkeiten, Funktionen zu deklarieren:
Die Codekopie lautet wie folgt:
// die Funktion myfunc direkt deklarieren
Funktion myfunc (/ * Argumente */) {
}
// Weisen Sie dem lokalen variablen MyFunc anonyme Funktionen zu
var myfunc = Funktion (/ * Argumente */) {
}
Beachten Sie, dass es in den beiden oben genannten Methoden der Deklaration von Funktionen subtile Unterschiede gibt: Die erste Methode ist eine benannte Funktion, wenn sie deklariert wird, unabhängig davon, ob es sich um eine deklarierte Funktion vor, nach dem Anruf oder sogar der Ort, an dem sie nicht ausgeführt wird (z. B. nach der Rückkehrerklärung oder in einem Zweig, der niemals wahr sein wird), ist in der gesamten Diskussion zugänglich. Die zweite Methode besteht darin, Variablen anonyme Funktionen zuzuweisen. Streng genommen ist dies keine Funktionserklärung, sondern ein Funktionsausdruck. Vor der Zuweisung kann auf diese Funktion nicht mit einem Code zugegriffen werden, was bedeutet, dass die Zuordnung vor dem Anruf ausgeführt werden muss. Andernfalls erscheint ein Fehler beim Aufrufen: "TypeError: undefined ist keine Funktion". Zum Beispiel:
Die Codekopie lautet wie folgt:
myfunc1 (); // kann normal aufgerufen werden, da MyFunc1 eine direkte Deklarationsmethode verwendet
Funktion myfunc1 () {
}
myfunc2 (); // Fehler typeerror: undefined ist keine Funktion
var myfunc2 = function () {
};
Die grundlegende Aufrufmethode der Funktionen wird auf die gleiche Weise wie in traditionellen Sprachen aufgerufen: myfunc (). JavaScript -Funktionen unterstützen auch direkte oder indirekte rekursive Anrufe. Beispielsweise kann die klassische Fibonacci -Funktion in JavaScript wie folgt implementiert werden:
Die Codekopie lautet wie folgt:
Funktion Fib (n) {
if (n == 1 || n == 2) {
Rückkehr 1;
} anders {
Return Fib (n - 2) + Fib (n - 1);
}
}
Funktionen in JavaScript können Parameter mit variabler Länge verarbeiten. Sie alle haben eine lokale Variable, die als Argumente in der Funktion bezeichnet wird. Es ist ein Array-ähnliches Objekt, das alle beim Aufrufen übergebenen Parameter enthält und ein Längenattribut für die Anzahl der Parameter darstellt. Zum Beispiel:
Die Codekopie lautet wie folgt:
Funktionstest () {
alarm (Argumente.Length);
}
Test (1); // 1
Test (1, 'a'); // 2
test (true, [], {}); // 3 Verwenden Sie Argumente, um Funktionen in der C -Sprache ähnlich zu implementieren, und können auch zur Implementierung des Polymorphismus von Methoden verwendet werden.
2. Erweiterte JavaScript -Funktionen
2.1 Anonyme und verschachtelte Funktionen
In JavaScript können Sie eine Funktion ohne einen Namen deklarieren, der als anonyme Funktion (anonyme Funktion) bezeichnet wird. Gleichzeitig ermöglicht JavaScript auch die Funktionserklärung innerhalb von Funktionen, die als verschachtelte Funktionen bezeichnet werden, und der Umfang verschachtelter Funktionen ist die gesamte übergeordnete Funktion.
Im vorherigen Teil der Funktionserklärung sah ich eine Verwendung anonymer Funktionen und verschachtelte Funktionen. Da anonyme Funktionen keinen Namen haben, werden sie keine neuen Variablen einführen, um den Kontext zu verschmutzen und neue variable Bereiche zu bringen. Daher werden anonyme Funktionen häufig verwendet, um die globale Umweltverschmutzung zu verhindern.
In der JavaScript -Laufzeit gibt es ein spezielles globales Objekt. Dieses Objekt speichert globale Funktionen und Variablen. In der tatsächlichen Entwicklung werden häufig mehrere Bibliotheken oder mehrere JS-Dateien von Drittanbietern verwendet. Wenn Sie versehentlich doppelte Variablen oder Funktionserklärungen in das globale Objekt einführen, wird die Codeausführung verwirrt. Beispielsweise werden zwei JS -Dateien nacheinander eingeführt, und ihr eigenes Funktionsprotokoll wird als interne Verwendung definiert. Die zweite eingeführte Funktion überschreibt die Definition des ersten und wirft keine Fehler. Das Aufrufen der Protokollfunktion in der nachfolgenden Ausführung kann einen Fehler verursachen. Zu diesem Zeitpunkt kann die Verwendung einer anonymen Funktion zum Wickeln der Logik in den gesamten JS diesen Fehler vermeiden. Diese Methode wurde von den meisten Open -Source -JS -Bibliotheken verwendet.
Die Codekopie lautet wie folgt:
(function () {// anonyme Funktion
Funktion log (msg) {
console.log (msg);
}
// andere Codes
} ()); // sofort ausführen
Der obige Code ist ein einfaches Beispiel. Der Umfang der Protokollfunktion ist auf diese anonyme Funktion beschränkt. Die anonyme Funktion ist in zwei Klammern () außerhalb des Außenbereichs enthalten, um einen Funktionsausdruck zu bilden. Der Wert des Ausdrucks ist eine Funktion, gefolgt von zwei Klammern, um anzuzeigen, dass die Funktion sofort ausgeführt wird, damit der ursprüngliche Code normal ausgeführt werden kann. Auf diese Weise deklarierte Funktionen, durch VAR usw. deklarierte Variablen sind jedoch intern und können von einem anderen Code als anonymen Funktionen nicht zugegriffen werden. Wenn Sie einige Funktionen als Schnittstellen aufdecken müssen, gibt es verschiedene Methoden:
Die Codekopie lautet wie folgt:
var Mylib = (Funktion (global) {
Funktion log (msg) {
console.log (msg);
}
log1 = log; // Methode 1: Verwenden Sie das Standardverhalten der Variablendeklaration ohne VAR, um eine globale Variable in log1 zu werden (nicht empfohlen)
global.log2 = log; // Methode 2: Fügen Sie dem globalen Objekt direkt Log2 -Attribut hinzu und weisen Sie es einer Protokollfunktion zu (empfohlen).
Return {// Methode 3: Geben Sie eine Reihe von Schnittstellenfunktionserfassungsobjekten über anonyme Funktionen zurück und weisen Sie sie der globalen variablen MYLIB zu (empfohlen).
Protokoll: Protokoll
};
}(Fenster));
2.2 Funktion hoher Ordnung
Wenn eine Funktion als Parameter oder Rückgabewert verwendet wird, wird sie als Funktion höherer Ordnung bezeichnet. Funktionen in JavaScript können als Funktionen höherer Ordnung verwendet werden, was auch eine Funktion der ersten Art von Funktionen ist. Lassen Sie uns diese beiden Nutzungsmethoden unten analysieren.
Die Codekopie lautet wie folgt:
Funktion negativ (n) {
return -n; // Nehmen Sie den entgegengesetzten Wert von n
}
Funktion Square (n) {
return n*n; // Quadrat von n
}
Funktionsprozess (NUMS, Rückruf) {
var result = [];
für (var i = 0, Länge = nums.length; i <Länge; i ++) {
Ergebnis [i] = callback (nums [i]); // Übergeben Sie alle Elemente in den Array -NUMs zur Verarbeitung an einen Rückruf und speichern Sie den Rückgabewert als Ergebnis
}
Rückgabeergebnis;
}
var nums = [-3, -2, -1, 0, 1, 2, 3, 4];
var n_neg = prozess (nums, negativ);
// n_neg = [3, 2, 1, 0, -1, -2, -3, -4];
var n_square = prozess (nums, quadratisch);
// n_square = [9, 4, 1, 0, 1, 4, 9, 16];
Der obige Code zeigt ein Beispiel für das Übergeben einer Funktion als Parameter in einen anderen Funktionsprozessaufruf. Bei der Implementierung der Prozessfunktion wird Callback als schwarzer Box angesehen, das für die Übergabe des Parameters an ihn und dann den Rückgabewert erhalten wird. Die spezifische Implementierung des Rückrufs ist vor dem Anruf nicht klar. Nur wenn 20- und 22 -Zeilen ausgeführt werden, wird Rückruf negativ bzw. quadratisch dargestellt, und jedes Element wird mit dem entgegengesetzten Wert oder dem quadratischen Wert genommen.
Die Codekopie lautet wie folgt:
Funktionsgenerator () {
var i = 0;
return function () {
return i ++;
};
}
var gen1 = generator (); // Erhalten Sie einen natürlichen Zahlengenerator
var Gen2 = Generator (); // Holen Sie sich einen weiteren natürlichen Zahlengenerator
var r1 = gen1 (); // R1 = 0
var r2 = gen1 (); // R2 = 1
var r3 = gen2 (); // r3 = 0
var r4 = gen2 (); // R4 = 1
Der obige Code zeigt ein Beispiel für die Verwendung einer Funktion als Rückgabewert. Generator ist eine natürliche Nummerngeneratorfunktion, und der Rückgabewert ist eine natürliche Zahlengeneratorfunktion. Jedes Mal, wenn Generator aufgerufen wird, wird eine anonyme Funktion als Ergebnis zurückgegeben. Diese anonyme Funktion gibt jede natürliche Zahl wiederum zurück, wenn sie tatsächlich aufgerufen wird. Die Variable I im Generator erhöht sich jedes Mal um 1, wenn diese anonyme Funktion aufgerufen wird, was tatsächlich ein Verschluss ist. Lasst uns unten Schließungen vorstellen.
2.3 Schließung
Schließungen sind kein neues Konzept, und viele funktionale Sprachen verwenden Verschlüsse. In JavaScript verwenden Sie, wenn Sie Variablen im Bereich der externen Funktionen in einer eingebetteten Funktion verwenden, Verschlüsse. Verwenden Sie eine häufig verwendete Analogie, um die Beziehung zwischen einem Verschluss und einer Klasse zu erklären: Eine Klasse sind Daten mit Funktionen, und ein Verschluss ist eine Funktion mit Daten.
Variablen, die in Verschluss verwendet werden, haben ein Merkmal, dass sie nicht freigegeben werden, wenn die Elternfunktion zurückkehrt, sondern mit dem Ende des Lebenszyklus des Verschlusss enden. Zum Beispiel verwenden wie im Generatorbeispiel im vorherigen Abschnitt Gen1 und Gen2 unabhängige Variablen i (wenn Gen1s I durch 1 erhöht wird, wird ich nicht betroffen sein und umgekehrt). Solange die beiden Variablen Gen1 oder Gen2 von der JavaScript -Engine nicht Müll erfasst werden, werden ihre jeweiligen Variablen nicht freigesetzt. Bei der JavaScript -Programmierung werden Schließungen unbewusst eingesetzt. Diese Funktion von Verschlüssen ist einfach zu bedienen, führt aber auch leicht zu Problemen mit Speicherlecks. Zum Beispiel:
Die Codekopie lautet wie folgt:
var elem = document.getElementById ('test');
elem.addeventListener ('klick', function () {
alert ('du klickte' + elem.tagname);
});
Der Zweck dieses Codes ist es, seinen Labelnamen beim Klicken auf einen Knoten anzuzeigen. Es registriert eine anonyme Funktion als Klickereignisbearbeitungsfunktion eines DOM -Knotens. Ein DOM -Objekt Elem wird in der Funktion verwiesen, die einen Verschluss bildet. Dies erzeugt eine kreisförmige Referenz, dh DOM-> CLOSSARY-> DOM-> CLOSSARY ... Das DOM-Objekt wird nicht vor der Freigabe des Verschlusses freigegeben. und der Verschluss existiert als Ereignisbearbeitungsfunktion des DOM -Objekts, sodass der Verschluss nicht freigegeben wird, bevor das DOM -Objekt veröffentlicht wird. Auch wenn das DOM -Objekt aufgrund der Existenz dieser kreisförmigen Referenz im DOM -Baum gelöscht wird, werden weder das DOM -Objekt noch der Schließen freigegeben. Dieses Speicherleck kann mit den folgenden Methoden vermieden werden:
Die Codekopie lautet wie folgt:
var elem = document.getElementById ('test');
elem.addeventListener ('klick', function () {
alert ('du klickte' + this.tagname); // Nicht mehr direkt verweist die ELEM -Variable
});
Im obigen Code wird dies anstelle von Elem verwendet (dieser Zeiger zeigt auf das DOM -Element selbst in der DOM -Ereignishandhabungsfunktion), so dass die JS -Laufzeit nicht mehr der Ansicht ist, dass die Funktion die übergeordneten Klassenvariablen verwendet, sodass kein Verschluss mehr bildet.
Verschlüsse bringen auch viele ähnliche Speicher -Leck -Probleme. Sie können beim Schreiben von Code nur auf Schließungen achten und versuchen, solche Probleme zu vermeiden.
2.4 Klassenkonstruktor
JavaScript -Funktionen werden auch als Klassenkonstruktoren verwendet, sodass Sie das neue Schlüsselwort verwenden können, um eine Instanz der Klasse zu erstellen, solange Sie eine Funktion deklarieren.
Die Codekopie lautet wie folgt:
Funktionsperson (Name) {
this.name = name;
this.toString = function () {
zurück 'Hallo,' + this.name + '!';
};
}
var p = neue Person ('GhostheAven');
Alarm (p); // Hallo, Ghostheaven! Im obigen Beispiel wird die Personfunktion als Klassenkonstruktor verwendet. Zu diesem Zeitpunkt weist dies auf das neu erstellte Instanzobjekt hin und kann der Instanz Eigenschaften und Methoden hinzufügen. Ausführliche objektorientierte JavaScript-Programmierung finden Sie in diesem Artikel. Was ich hier sagen möchte, ist das Rückgabewertproblem bei der Verwendung von JavaScript -Funktionen als Klassenkonstruktoren.
Die Codekopie lautet wie folgt:
Funktion MyClass (Name) {
this.name = name;
Rückgabename; // Der Rückgabewert des Konstruktors?
}
var obj1 = new myclass ('foo');
var obj2 = myclass ('foo');
var obj3 = new MyClass ({});
var obj4 = myClass ({});
Der obige Konstruktor ist etwas Besonderes mit einer Rückgabeerklärung. Auf welche Objekte verweisen OBJ1 ~ OBJ4? Das tatsächliche Ergebnis ist Folgendes:
Die Codekopie lautet wie folgt:
OBJ1 = MyClass -Objekt
obj2 = 'foo' '
obj3 = {}
obj4 = {}
Die spezifischen Gründe werden in diesem Artikel erläutert, und ich werde es in diesem Artikel nicht wiederholen. Da Konstruktoren mit Rückgabetwerten seltsame Ergebnisse erzielen, rufen Sie keine Rückgabeanweisungen mit Rückgabewerten im Konstruktor auf (leere Rendite kann erfolgen).
3.. JavaScript Funktionen Monster Level
Willkommen im Funktionsbereich der Monster-Ebene, wo Sie sich ruhig und frei dem alten Monster dem alten Monster stellen können. . .
3.1 Funktionsklasse
In der JavaScript-Laufzeit gibt es eine integrierte Klasse, die als Funktion bezeichnet wird. Das Deklarieren einer Funktion mit dem Schlüsselwort für Funktion ist tatsächlich eine Abkürzung zum Erstellen von Funktionsklassenobjekten. Alle Funktionen haben alle Methoden der Funktionsklasse, z. B. Anruf, Anwendung, Binden usw. Sie können diese Anweisung über das Schlüsselwort Instanceof überprüfen.
Da die Funktion eine Klasse ist, ist sein Konstruktor die Funktion (sie ist selbst ein Objekt der Funktionsklasse), und ein Funktionsobjekt sollte über das neue Schlüsselwort generiert werden. Das erste Monster ist hier, nämlich wie man eine Funktion mit der Funktionsklasse erstellt. Die Funktionssyntax ist wie folgt:
Die Codekopie lautet wie folgt:
Neue Funktion ([arg1 [, arg2 [, ... argn]],] functionbody)
wobei Arg1, Arg2, ... Argn eine Zeichenfolge ist, die den Parameternamen und FunktionBody auch eine Zeichenfolge darstellt, die den Funktionskörper darstellt. Der vorherige Parametername ist mehr oder weniger. Der Funktionskonstruktor behandelt den letzten Parameter als Funktionskörper und die vorherigen als Parameter.
Die Codekopie lautet wie folgt:
var func1 = neue Funktion ('Name', 'return "Hallo," + name + "!";');
Func1 ('GhostheAven'); // Hallo, Ghostheaven!
Die obige Methode konstruiert eine Funktion durch die Funktion, die genau mit anderen Funktionen übereinstimmt, die mit dem Schlüsselwort der Funktion deklariert sind.
Wenn man das sieht, fragen sich viele Menschen möglicherweise, warum ein solches Monster benötigt wird? "Was existiert ist, ist vernünftig", die Funktionsklasse hat ihren einzigartigen Zweck. Sie können es verwenden, um dynamisch verschiedene Funktionslogik zu generieren oder die Funktionen der Eval -Funktion zu ersetzen und zu verhindern, dass die aktuelle Umgebung verschmutzt wird*.
3.2 Selbst-Update-Funktion
In vielen Sprachen kann eine Funktion, sobald sie deklariert wurde, die Funktion desselben Namens nicht erneut deklarieren, andernfalls treten Syntaxfehler auf. Funktionen in JavaScript können nicht nur wiederholt deklariert werden, sondern auch selbst aktualisieren. Das Monster, das ich esse, ist hier!
Die Codekopie lautet wie folgt:
Funktion selfUpdate () {
window.elfupdate = function () {
alarm ('zweiter Lauf!');
};
alarm ('Erster Lauf!');
}
selfupdate (); // Erster Lauf!
selfupdate (); // zweiter Lauf! Diese Funktion kann für die Logik verwendet werden, die nur einmal ausgeführt wird, und nach dem ersten Lauf wird sie durch ein neues Stück Logik ersetzt.
Zusammenfassung
Die Funktionen von JavaScript sind sehr mächtig. Während sie viele Probleme wunderbar lösen, bringen sie auch viele negative Probleme mit sich. Monster-Level-Funktionen werden normalerweise mit wenig bekannter Verwendung verwendet. Sofern dies nicht besonders notwendig ist, wird dies zu Lesen von Code führen und die Effizienz der Teamentwicklung beeinflussen.
* Ein strikter Modus wurde im neuen ECMascript eingeführt. Im strengen Modus ist die EV -Funktion stark eingeschränkt und kann sicherstellen, dass die Umwelt nicht verschmutzt ist.
Verstehst du, es ist sehr praktisch. Wenn es fehlende Orte gibt, geben Sie mir bitte einen Rat und machen Sie gemeinsam Fortschritte.