Pfeilfunktionen in JavaScript: Warum werden sie benötigt, wie sie gehandhabt werden, wann sie verwendet werden sollen und wann nicht

Ursprünglicher Autor: Kevin Ball
  • Übersetzung
Eine der bemerkenswertesten Neuerungen im modernen JavaScript ist das Aufkommen von Pfeilfunktionen (Pfeilfunktion), die manchmal als "Fettpfeilfunktionen" (Fettpfeilfunktion) bezeichnet werden. Verwenden Sie bei der Deklaration solcher Funktionen eine spezielle Zeichenkombination - =>.

Schalterfunktionen haben zwei Hauptvorteile gegenüber herkömmlichen Funktionen. Die erste ist eine sehr bequeme und kompakte Syntax. Die zweite ist, dass der Ansatz, mit dem Wert thisin den Schalterfunktionen zu arbeiten, intuitiver aussieht als bei den normalen Funktionen.

Bild

Manchmal führen diese und andere Vorteile dazu, dass die Switch-Syntax den anderen Methoden der Funktionsdeklaration vorbehaltlos vorgezogen wird. Die populäre Eslint-Konfiguration von Airbnb erzwingt beispielsweise, dass eine solche Funktion immer dann ist, wenn eine anonyme Funktion erstellt wird.

Wie andere Konzepte und Mechanismen, die bei der Programmierung verwendet werden, haben die Schalterfunktionen jedoch ihre Vor- und Nachteile. Ihre Verwendung kann negative Nebenwirkungen verursachen. Um die Switch-Funktionen korrekt verwenden zu können, müssen Sie die möglichen Probleme kennen, die damit verbunden sind.

In dem Material, dessen Übersetzung wir heute veröffentlichen, werden wir darüber sprechen, wie der Switch funktioniert. Hier werden Situationen betrachtet, in denen ihre Verwendung den Code verbessern kann, und Situationen, in denen sie nicht verwendet werden sollten.

Funktionen der Pfeilfunktionen in JavaScript


Pfeilfunktionen in Javascript sind so etwas wie Lambda-Funktionen in Python und Blöcke in Ruby.

Hierbei handelt es sich um anonyme Funktionen mit einer speziellen Syntax, die eine feste Anzahl von Argumenten annehmen und im Kontext ihres Gültigkeitsbereichs arbeiten, d. H. Im Kontext einer Funktion oder eines anderen Codes, in dem sie deklariert sind.

Lassen Sie uns näher darauf eingehen.

СтрелDie Syntax der Switch-Funktionen


Pfeilfunktionen sind nach einem einheitlichen Schema aufgebaut, und die Struktur der Funktionen kann in besonderen Fällen vereinfacht werden. Die grundlegende Struktur der Pfeilfunktion sieht folgendermaßen aus:

(argument1, argument2, ... argumentN) => {
  // тело функции
}

Die Liste der Funktionsargumente steht in Klammern, gefolgt von einem Pfeil, bestehend aus Symbolen =und >, und der Funktionskörper ist in geschweiften Klammern.

Dies ist der Anordnung gewöhnlicher Funktionen sehr ähnlich. Die Hauptunterschiede bestehen darin, dass das Schlüsselwort hier weggelassen wird functionund der Pfeil nach der Argumentliste hinzugefügt wird.

In bestimmten Fällen können jedoch einfache Pfeilfunktionen mit wesentlich kompakteren Konstruktionen deklariert werden.

Betrachten Sie eine Variante der Syntax, die verwendet wird, wenn der Funktionskörper durch einen einzelnen Ausdruck dargestellt wird. Damit können Sie auf geschweifte Klammern verzichten, die den Rumpf der Funktion einrahmen, und die Notwendigkeit, die Ergebnisse der Auswertung des Ausdrucks explizit zurückzugeben, da dieses Ergebnis automatisch zurückgegeben wird. Zum Beispiel könnte es so aussehen:

const add = (a, b) => a + b;

Hier ist eine andere Version der abgekürzten Funktion write, die verwendet wird, wenn die Funktion nur ein Argument hat.

const getFirst = array => array[0];

Wie Sie sehen, werden hier die Klammern, die die Argumentliste einrahmen, weggelassen. Außerdem wird der Funktionsrumpf, der in diesem Beispiel durch einen einzelnen Befehl dargestellt wird, auch ohne Klammern geschrieben. Später werden wir mehr über die Vorteile solcher Strukturen sprechen.

▍Zurückgabe von Objekten und gekürzte Aufzeichnung von Zeigerfunktionen


Beim Arbeiten mit den Pfeilfunktionen werden einige komplexere Syntaxstrukturen verwendet, die hilfreich sind, um darüber zu wissen.

Versuchen wir beispielsweise, einen einzeiligen Ausdruck zu verwenden, um ein Objektliteral aus einer Funktion zurückzugeben. In Anbetracht dessen, was wir bereits über die Pfeilfunktionen wissen, kann die Funktionsdeklaration so aussehen:

(name, description) => {name: name, description: description};

Das Problem bei diesem Code ist seine Mehrdeutigkeit. Die geschweiften Klammern, mit denen wir das Objekt-Literal beschreiben möchten, sehen aus, als würden wir versuchen, den Funktionskörper in sie einzuschließen.

Um dem System anzuzeigen, dass wir das Objektliteral meinen, müssen wir es in Klammern einschließen:

(name, description) => ({name: name, description: description});

▍Fischer und deren Ausführungskontext


Im Gegensatz zu anderen Funktionen haben die Switch-Funktionen keinen eigenen Ausführungskontext .

In der Praxis bedeutet dies, dass sie die Entität thisund argumentsvon der übergeordneten Funktion erben .

Vergleichen Sie beispielsweise die beiden Funktionen, die im folgenden Code dargestellt werden. Einer von ihnen ist normal, der zweite Pfeil.

const test = {
  name: 'test object',
  createAnonFunction: function() {
    returnfunction() {
      console.log(this.name);
      console.log(arguments);
    };
  },
  createArrowFunction: function() {
    return() => {
      console.log(this.name);
      console.log(arguments);
    };
  }
};

Es gibt ein Objekt testmit zwei Methoden. Jede von ihnen ist eine Funktion, die eine anonyme Funktion erstellt und zurückgibt. Der Unterschied zwischen diesen Methoden liegt nur in der Tatsache, dass in der ersten Methode der traditionelle Funktionsausdruck verwendet wird und in der zweiten die Pfeilfunktion.

Wenn Sie mit diesem Code in der Konsole experimentieren und die gleichen Argumente an die Methoden des Objekts übergeben, werden die Methoden zwar sehr ähnlich aussehen, wir erhalten jedoch andere Ergebnisse:

> const anon = test.createAnonFunction('hello', 'world');
> const arrow = test.createArrowFunction('hello', 'world');
> anon();
undefined
{}
> arrow();
test object
{ '0': 'hello', '1': 'world' }

Eine anonyme Funktion hat einen eigenen Kontext. Beim Aufruf wird test.nameder Wert der nameObjekteigenschaft beim Aufruf argumentsnicht angezeigt . Beim Zugriff wird die Liste der Argumente der Funktion, mit der die untersuchte Funktion erstellt und zurückgegeben wurde, nicht angezeigt.

Bei der arrow-Funktion stellt sich heraus, dass ihr Kontext mit dem Kontext der erstellenden Funktion übereinstimmt, wodurch sie sowohl auf die Liste der von dieser Funktion übergebenen Argumente als auch auf die Eigenschaft des nameObjekts zugreifen kann, dessen Methode diese Funktion ist.

Situationen, in denen die Switch-Funktionen den Code verbessern


▍Verarbeitungslisten von Werten


Traditionelle Lambda-Funktionen sowie Pfeilfunktionen werden nach ihrem Auftreten in JavaScript normalerweise in Situationen verwendet, in denen eine bestimmte Funktion auf jedes Element einer bestimmten Liste angewendet wird.

Wenn beispielsweise ein Array von Werten vorhanden ist, das mit der Array-Methode konvertiert werden muss map, ist eine Pfeilfunktion ideal, um eine solche Konvertierung zu beschreiben:

const words = ['hello', 'WORLD', 'Whatever'];
const downcasedWords = words.map(word => word.toLowerCase());

Hier ist ein äußerst verbreitetes Beispiel für diese Verwendung von Schalterfunktionen, die mit den Eigenschaften von Objekten arbeiten sollen:

const names = objects.map(object => object.name);

Wenn formoderne forEach, auf Iteratoren basierende Zyklen anstelle von herkömmlichen Zyklen verwendet werden , macht die Tatsache, dass die Switch-Funktionen die thisübergeordnete Entität verwenden, deren Verwendung intuitiv klar:

this.examples.forEach(example => {
  this.runExample(example);
});

Promotorisiert und verspricht Ketten


Eine andere Situation, in der Sie mit den Pfeilfunktionen saubereren und verständlicheren Code schreiben können, wird durch asynchrone Softwarekonstrukte dargestellt.

Also, PROMI erheblich die Arbeit mit dem asynchronen Code vereinfachen. Selbst wenn Sie es vorziehen, das async / await- Konstrukt zu verwenden, können Sie die Verheißungen nicht verstehen , da dieses Konstrukt darauf basiert.

Bei der Verwendung von Versprechungen müssen Sie jedoch Funktionen deklarieren, die nach dem Abschluss eines asynchronen Codes oder dem Abschluss eines asynchronen Aufrufs an eine API aufgerufen werden.

Dies ist ein idealer Ort für die Verwendung der Schaltfunktionen, insbesondere wenn die resultierende Funktion einen Zustand hat, der auf etwas im Objekt verweist. Zum Beispiel könnte es so aussehen:

this.doSomethingAsync().then((result) => {
  this.storeResult(result);
});

Объектов Transformation von Objekten


Ein anderes allgemeines Beispiel für die Verwendung von Switch-Funktionen ist das Einkapseln von Objekttransformationen.

In Vue.js gibt es beispielsweise ein allgemein akzeptiertes Muster, um Fragmente des Vuex-Speichers direkt in eine Vue-Komponente zu integrieren mapState.

Diese Operation umfasst Deklarationen eines Satzes von "Konvertern", die aus dem ursprünglichen Vollzustand genau auswählen, was für eine bestimmte Komponente benötigt wird.

Solche einfachen Transformationen sind ein idealer Ort für die Verwendung von Switch-Funktionen. Zum Beispiel:

exportdefault {
  computed: {
    ...mapState({
      results: state => state.results,
      users: state => state.users,
    });
  }
}

Situationen, in denen Sie die Pfeilfunktionen nicht verwenden sollten


Об .ектов Objektmethoden


Es gibt eine Reihe von Situationen, in denen die Verwendung von Schalterfunktionen nicht die beste Idee ist. Wenn die Pfeilfunktionen gedankenlos angewendet werden, helfen sie Programmierern nicht nur nicht, sondern werden auch zu Problemen.

Die erste derartige Situation ist die Verwendung von Schalterfunktionen als Methoden von Objekten. Hier sind der Ausführungskontext und das Schlüsselwort thischarakteristischer Funktionen von Bedeutung .

Zu einer Zeit war es üblich, eine Kombination aus Klasseneigenschaften und Switch-Funktionen zu verwenden, um Methoden mit "automatischer Bindung" zu erstellen, d. H. Solche, die von Event-Handlern verwendet werden können, aber an die Klasse gebunden bleiben. Es sah so aus:

classCounter {
  counter = 0;

  handleClick = () => {
    this.counter++;
  }
}

Bei Verwendung eines solchen Konstrukts hatte die Funktion Zugriff auf die Daten dieser Instanz , selbst wenn die Funktion handleClickvon einem Ereignishandler aufgerufen wurde und nicht im Kontext einer Instanz einer Klasse Counter.

Dieser Ansatz hat jedoch viele Nachteile, denen dieses Material gewidmet ist .

Obwohl die Verwendung der Pfeilfunktion hier sicherlich eine bequeme Art ist, eine Funktion zu binden, ist das Verhalten dieser Funktion in vielen Aspekten alles andere als intuitiv. Sie beeinträchtigt das Testen und Erstellen von Problemen in Situationen, in denen sie beispielsweise versuchen, das entsprechende Objekt als Prototyp zu verwenden.

Verwenden Sie in solchen Fällen anstelle der switch-Funktionen die üblichen Funktionen und binden Sie gegebenenfalls eine Instanz des Objekts im Konstruktor:

class Counter {
  counter = 0;
  handleClick() {
    this.counter++;
  }
  constructor(){
    this.handleClick = this.handleClick.bind(this);
  }
}

▍Lange Anrufketten


Pfeilfunktionen können zu Problemen führen, wenn sie in vielen verschiedenen Kombinationen eingesetzt werden sollen, insbesondere in langen Ketten von Funktionsaufrufen.

Der Hauptgrund für solche Probleme liegt, wie bei der Verwendung anonymer Funktionen, darin, dass sie extrem uninformative Ergebnisse der Aufrufstack- Ablaufverfolgung liefern .

Dies ist nicht so schlimm, wenn es zum Beispiel nur eine Verschachtelungsebene von Funktionsaufrufen gibt, wenn wir beispielsweise von der im Iterator verwendeten Funktion sprechen. Wenn jedoch alle verwendeten Funktionen als Zeigerfunktionen deklariert sind und sich gegenseitig Funktionen nennen, ist es nicht leicht zu verstehen, was passiert, wenn ein Fehler auftritt. Fehlermeldungen sehen etwa so aus:

{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()

▍Funktionen mit dynamischem Kontext


Die letzte der Situationen, in denen die Switch-Funktionen eine Problemquelle darstellen können, besteht darin, sie dort zu verwenden, wo Sie eine dynamische Verknüpfung benötigen this.

Wenn in solchen Situationen Zeigerfunktionen verwendet thiswerden, funktioniert das dynamische Ausrichten nicht. Diese unangenehme Überraschung lässt Sie über die Ursachen dessen nachdenken, was mit denen geschieht, die mit einem Code arbeiten müssen, in dem die Zeigerfunktionen falsch verwendet werden.

Folgendes sollten Sie bei der Verwendung der Wählfunktionen beachten:

  • Ereignishandler werden mit einem damit verknüpften thisEreignisattribut aufgerufen currentTarget.
  • Wenn Sie noch jQuery verwenden, denken Sie daran, dass die meisten jQuery-Methoden an thisdas ausgewählte DOM-Element gebunden sind .
  • Wenn Sie Vue.js verwenden, sind Methoden und berechnete Funktionen normalerweise an thisdie Vue-Komponente gebunden .

Selbstverständlich können die Switch-Funktionen gezielt eingesetzt werden, um das Standardverhalten von Softwaremechanismen zu ändern. Dies steht jedoch, besonders in den Fällen von jQuery und Vue, oft im Konflikt mit dem normalen Betrieb des Systems, was dazu führt, dass der Programmierer nicht verstehen kann, warum ein Code, der recht normal aussieht, plötzlich nicht mehr funktioniert.

Ergebnisse


Pfeilfunktionen sind eine großartige neue JavaScript-Funktion. In vielen Situationen können sie bequemeren Code schreiben als zuvor. Wie bei anderen Fähigkeiten haben sie jedoch sowohl Vor- als auch Nachteile. Daher müssen die Switch-Funktionen dort eingesetzt werden, wo sie nützlich sein können, ohne sie als vollständigen Ersatz für gewöhnliche Funktionen zu betrachten.

Liebe Leserinnen und Leser! Haben Sie Situationen erlebt, in denen die Verwendung von Switch-Funktionen zu Fehlern, Unannehmlichkeiten oder unerwartetem Verhalten von Programmen führt?


Jetzt auch beliebt: