Sind „Pfeilfunktionen“ und „Funktionen“ gleichwertig / austauschbar?

Lesezeit: 10 Minuten

Sind „Pfeilfunktionen und „Funktionen gleichwertig austauschbar
Felix Klinge

Pfeilfunktionen in ES2015 bieten eine prägnantere Syntax.

  • Kann ich jetzt alle meine Funktionsdeklarationen/Ausdrücke durch Pfeilfunktionen ersetzen?
  • Worauf muss ich achten?

Beispiele:

Konstruktorfunktion

function User(name) {
  this.name = name;
}

// vs

const User = name => {
  this.name = name;
};

Prototypische Methoden

User.prototype.getName = function() {
  return this.name;
};

// vs

User.prototype.getName = () => this.name;

Objekt (literale) Methoden

const obj = {
  getName: function() {
    // ...
  }
};

// vs

const obj = {
  getName: () => {
    // ...
  }
};

Rückrufe

setTimeout(function() {
  // ...
}, 500);

// vs

setTimeout(() => {
  // ...
}, 500);

Variadische Funktionen

function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// vs
const sum = (...args) => {
  // ...
};

  • Ähnliche Fragen zu Pfeilfunktionen sind immer häufiger aufgetaucht, da ES2015 immer beliebter wird. Ich hatte nicht das Gefühl, dass es eine gute kanonische Frage/Antwort für dieses Problem gibt, also habe ich diese erstellt. Wenn Sie der Meinung sind, dass es bereits eine gute gibt, lassen Sie es mich bitte wissen und ich werde diese als Duplikat schließen oder löschen. Fühlen Sie sich frei, die Beispiele zu verbessern oder neue hinzuzufügen.

    – Felix Klinge

    18. Dezember 2015 um 17:59 Uhr


  • Was ist mit JavaScript ecma6, um die normale Funktion in eine Pfeilfunktion zu ändern? Natürlich kann eine normale Frage niemals so gut und generisch sein wie eine, die speziell als kanonische Frage geschrieben wurde.

    – Bergi

    18. Dezember 2015 um 23:53 Uhr

  • Sehen Sie sich dieses Plnkr-Beispiel an Die Variable this ist sehr unterschiedlich timesCalled erhöht sich bei jedem Aufruf nur um 1. Was meine persönliche Frage beantwortet: .click( () => { } ) und .click(function() { }) beide erstellen die gleiche Anzahl von Funktionen, wenn sie in einer Schleife verwendet werden, wie Sie anhand der Guid-Anzahl im Plnkr sehen können.

    – jmbbild

    12. September 2016 um 14:01 Uhr

  • Verwandter Beitrag – Wann sollte ich Arrow-Funktionen in ECMAScript 6 verwenden?

    – RBT

    26. Juni 2019 um 8:36 Uhr

  • Siehe auch: Wie funktioniert das Schlüsselwort „this“?.

    – Sebastian Simon

    21. Juni 2021 um 6:43 Uhr

Sind „Pfeilfunktionen und „Funktionen gleichwertig austauschbar
Felix Klinge

tl;dr: Nein! Pfeilfunktionen und Funktionsdeklarationen/-ausdrücke sind nicht gleichwertig und können nicht blind ersetzt werden.
Wenn die Funktion, die Sie ersetzen möchten, funktioniert nicht verwenden this, arguments und wird nicht mit angerufen newdann ja.


Wie so oft: es hängt davon ab, ob. Pfeilfunktionen haben ein anderes Verhalten als Funktionsdeklarationen / -ausdrücke, also schauen wir uns zuerst die Unterschiede an:

1. Lexikalisch this und arguments

Pfeilfunktionen haben keine eigenen this oder arguments Bindung. Stattdessen werden diese Bezeichner im lexikalischen Gültigkeitsbereich wie jede andere Variable aufgelöst. Das bedeutet, dass innerhalb einer Pfeilfunktion this und arguments beziehen sich auf die Werte von this und arguments In der Umgebung ist die Pfeilfunktion definiert in (dh “außerhalb” der Pfeilfunktion):

// Example using a function expression
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

Im Fall des Funktionsausdrucks this bezieht sich auf das Objekt, das innerhalb der erstellt wurde createObject. Im Fall der Pfeilfunktion gilt: this bezieht sich auf this von createObject selbst.

Dies macht Pfeilfunktionen nützlich, wenn Sie auf die zugreifen müssen this der aktuellen Umgebung:

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

Notiz dass dies auch bedeutet, dass ist nicht möglich, eine Pfeilfunktion einzustellen this mit .bind oder .call.

Wenn Sie nicht sehr vertraut sind thiserwägen Sie zu lesen

2. Pfeilfunktionen können nicht mit aufgerufen werden new

ES2015 unterscheidet zwischen Funktionen, die sind Anrufin der Lage und Funktionen, die sind bauenfähig. Wenn eine Funktion konstruierbar ist, kann sie mit aufgerufen werden newdh new User(). Wenn eine Funktion aufrufbar ist, kann sie auch ohne aufgerufen werden new (dh normaler Funktionsaufruf).

Durch Funktionsdeklarationen / -ausdrücke erstellte Funktionen sind sowohl konstruierbar als auch aufrufbar.
Pfeilfunktionen (und Methoden) sind nur aufrufbar.
class Konstruktoren sind nur konstruierbar.

Wenn Sie versuchen, eine nicht aufrufbare Funktion aufzurufen oder eine nicht konstruierbare Funktion zu konstruieren, erhalten Sie einen Laufzeitfehler.


Wenn wir dies wissen, können wir Folgendes sagen.

Austauschbar:

  • Funktionen, die nicht verwendet werden this oder arguments.
  • Funktionen, die mit verwendet werden .bind(this)

Nicht austauschbar:

  • Konstruktorfunktionen
  • Funktion/Methoden, die einem Prototyp hinzugefügt wurden (weil sie normalerweise this)
  • Variadische Funktionen (wenn sie verwenden arguments (siehe unten))
  • Generatorfunktionen, die die function* Notation

Schauen wir uns das anhand Ihrer Beispiele genauer an:

Konstruktorfunktion

Dies funktioniert nicht, da Pfeilfunktionen nicht mit aufgerufen werden können new. Verwenden Sie weiterhin eine Funktionsdeklaration / einen Ausdruck oder verwenden Sie sie class.

Prototypische Methoden

Höchstwahrscheinlich nicht, da normalerweise Prototypmethoden verwendet werden this um auf die Instanz zuzugreifen. Wenn sie nicht verwenden this, dann kannst du es ersetzen. Wenn Sie jedoch in erster Linie Wert auf eine präzise Syntax legen, verwenden Sie class mit seiner prägnanten Methodensyntax:

class User {
  constructor(name) {
    this.name = name;
  }
  
  getName() {
    return this.name;
  }
}

Objektmethoden

Ähnlich für Methoden in einem Objektliteral. Wenn die Methode das Objekt selbst über referenzieren möchte thisverwenden Sie weiterhin Funktionsausdrücke oder verwenden Sie die neue Methodensyntax:

const obj = {
  getName() {
    // ...
  },
};

Rückrufe

Es hängt davon ab, ob. Sie sollten es auf jeden Fall ersetzen, wenn Sie das Äußere aliasieren this oder verwenden .bind(this):

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

Aber: Wenn der Code, der den Callback aufruft, explizit setzt this auf einen bestimmten Wert, wie es oft bei Event-Handlern der Fall ist, insbesondere bei jQuery, und die Callback-Verwendungen this (oder arguments), Sie kann nicht Verwenden Sie eine Pfeilfunktion!

Variadische Funktionen

Da Pfeilfunktionen keine eigenen haben arguments, Sie können sie nicht einfach durch eine Pfeilfunktion ersetzen. ES2015 führt jedoch eine Alternative zur Verwendung ein arguments: der Ruheparameter.

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};

Verwandte Frage:

  • Wann sollte ich Pfeilfunktionen in ECMAScript 6 verwenden?
  • Haben ES6-Pfeilfunktionen ihre eigenen Argumente oder nicht?
  • Was sind die Unterschiede (falls vorhanden) zwischen ES6-Pfeilfunktionen und Funktionen, die mit Function.prototype.bind gebunden sind?
  • Wie verwendet man Pfeilfunktionen (öffentliche Klassenfelder) als Klassenmethoden?

Weitere Ressourcen:

  • Erwähnenswert ist vielleicht, dass die lexikalische this wirkt sich auch aus super und dass sie keine haben .prototype.

    – loganfsmyth

    18. Dezember 2015 um 22:13 Uhr

  • Es wäre auch gut zu erwähnen, dass sie syntaktisch nicht austauschbar sind — eine Pfeilfunktion (AssignmentExpression) kann nicht einfach überall ein Funktionsausdruck (PrimaryExpression).

    – JMM

    1. April 2016 um 22:49 Uhr

  • @JMM: “Es bringt Leute ziemlich häufig zum Stolpern” kannst du ein konkretes beispiel nennen? Wenn Sie die Spezifikation überfliegen, scheint es, dass die Stellen, an denen Sie ein FE, aber kein AF platzieren können, sowieso zu Laufzeitfehlern führen würden …

    – Felix Klinge

    1. April 2016 um 22:54 Uhr

  • Sicher, ich meine Dinge wie den Versuch, sofort eine Pfeilfunktion wie einen Funktionsausdruck (() => {}()) oder so etwas tun x || () => {}. Das meine ich: Laufzeit-(Parse-)Fehler. (Und obwohl das der Fall ist, denken die Leute ziemlich häufig, dass der Fehler ein Fehler ist.) Versuchen Sie nur, logische Fehler abzudecken, die unbemerkt bleiben würden, weil sie nicht unbedingt Fehler machen, wenn sie analysiert oder ausgeführt werden? new‘ing one ist ein Laufzeitfehler, oder?

    – JMM

    1. April 2016 um 23:27 Uhr

  • Hier sind einige Links davon, die in freier Wildbahn auftauchen: substack/node-browserify#1499, babel/babel-eslint#245 (Dies ist ein asynchroner Pfeil, aber ich denke, es ist das gleiche grundlegende Problem) und eine Reihe von Problemen auf Babel, die jetzt schwer zu finden sind, aber hier ist eines T2847.

    – JMM

    1. April 2016 um 23:27 Uhr

Sind „Pfeilfunktionen und „Funktionen gleichwertig austauschbar
Aschutosch

Pfeilfunktionen => bisher beste ES6-Funktion. Sie sind eine enorm leistungsstarke Ergänzung zu ES6, die ich ständig verwende.

Warten Sie, Sie können die Pfeilfunktion nicht überall in Ihrem Code verwenden, es wird nicht in allen Fällen funktionieren this wo Pfeilfunktionen nicht verwendbar sind. Ohne Zweifel ist die Pfeilfunktion eine großartige Ergänzung, die Code-Einfachheit bringt.

Aber Sie können keine Pfeilfunktion verwenden, wenn ein dynamischer Kontext erforderlich ist: Methoden definieren, Objekte mit Konstruktoren erstellen, das Ziel davon erhalten, wenn Sie Ereignisse behandeln.

Pfeilfunktionen sollten NICHT verwendet werden, weil:

  1. Sie haben nicht this

    Es verwendet „lexical scoping“, um herauszufinden, was der Wert von „this” sollte sein. Im einfachen lexikalischen Scoping verwendet es „this” aus dem Inneren des Körpers der Funktion.

  2. Sie haben nicht arguments

    Pfeilfunktionen haben kein arguments Objekt. Die gleiche Funktionalität kann jedoch mit Restparametern erreicht werden.

    let sum = (...args) => args.reduce((x, y) => x + y, 0)
    sum(3, 3, 1) // output - 7

    `

  3. Sie können nicht mit verwendet werden new

    Pfeilfunktionen können keine Konstruktoren sein, da sie keine Prototypeigenschaft haben.

Wann Sie die Pfeilfunktion verwenden und wann nicht:

  1. Verwenden Sie nicht, um eine Funktion als Eigenschaft im Objektliteral hinzuzufügen, da wir darauf nicht zugreifen können.
  2. Funktionsausdrücke eignen sich am besten für Objektmethoden. Pfeilfunktionen eignen sich am besten für Rückrufe oder Methoden wie map, reduceoder forEach.
  3. Verwenden Sie Funktionsdeklarationen für Funktionen, die Sie namentlich aufrufen würden (weil sie gehisst sind).
  4. Verwenden Sie Pfeilfunktionen für Rückrufe (weil sie dazu neigen, knapper zu sein).

  • die 2. Sie haben keine Argumente, tut mir leid, ist nicht wahr, man kann Argumente haben, ohne den Operator … zu verwenden, vielleicht möchten Sie sagen, dass Sie kein Array als Argument haben

    – Karmin Tambascia

    2. März 2020 um 10:32 Uhr


  • @CarmineTambascia Lesen Sie mehr über das Special arguments Objekt, das hier nicht in Pfeilfunktionen verfügbar ist: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – Vichel

    16. April 2020 um 10:23 Uhr

1646897112 789 Sind „Pfeilfunktionen und „Funktionen gleichwertig austauschbar
todmo

Verwenden von Pfeilfunktionen mit function.prototype.callhabe ich eine Hilfsfunktion für den Objektprototyp erstellt:

  // Using
  // @func = function() {use this here} or This => {use This here}
  using(func) {
    return func.call(this, this);
  }

Verwendungszweck

  var obj = {f:3, a:2}
  .using(This => This.f + This.a) // 5

Bearbeiten

Sie brauchen keinen Helfer. Du könntest es tun:

var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5

Sie sind nicht immer gleichwertig. Hier ist ein Fall, in dem Sie nicht einfach Pfeilfunktionen anstelle von regulären Funktionen verwenden können.

Pfeilfunktionen können NICHT als Konstruktoren verwendet werden

TLDR:

Dies liegt daran, wie Pfeilfunktionen die verwenden Das Stichwort. JS gibt einfach einen Fehler aus, wenn es sieht, dass eine Pfeilfunktion als “Konstruktor” aufgerufen wird. Verwenden Sie reguläre Funktionen, um den Fehler zu beheben.

Längere Erklärung:

Dies liegt daran, dass Objekt-“Konstruktoren” auf die angewiesen sind Das Schlüsselwort geändert werden kann.

Im Allgemeinen die Das Das Schlüsselwort verweist immer auf das globale Objekt. (Im Browser ist es die Fenster Objekt).

ABER, wenn Sie so etwas tun:

function personCreator(name) {
   this.name = name;
}

const person1 = new personCreator('John');

Die Neu Schlüsselwort macht etwas von seiner Magie und macht die Das Schlüsselwort, das innerhalb von ist PersonErsteller zunächst ein leeres Objekt sein, anstatt auf das globale Objekt zu verweisen. Danach rief eine neue Eigenschaft an Name wird in diesem leeren erstellt Das Objekt, und sein Wert wird ‘John’ sein. Am Ende, die Das Objekt wird zurückgegeben.

Wie wir sehen, die Neu Schlüsselwort hat den Wert von geändert Das vom Verweis auf die global Objekt ist jetzt ein leeres Objekt {}.

Pfeilfunktionen lassen ihre nicht zu Das zu änderndes Objekt. Ihr Das Objekt ist immer dasjenige aus dem Gültigkeitsbereich, in dem sie statisch erstellt wurden. Das nennt man Statischer lexikalischer Umfang. Deshalb können Sie keine Operationen wie durchführen binden, anwendenoder Anruf mit Pfeilfunktionen. Einfach ihre Das ist auf den Wert von gesperrt Das des Geltungsbereichs, in dem sie erstellt wurden. Dies ist beabsichtigt.

Und aus diesem Grund: D können Pfeilfunktionen nicht als “Konstruktoren” verwendet werden.

Randnotiz:

Ein lexikalischer Gültigkeitsbereich ist nur der Bereich, in dem eine Funktion erstellt wird. Zum Beispiel:

function personCreator(name) {
    this.name = name;

    const foo = () => {
        const bar = () => {
            console.log(this); // Output: { name: 'John' }
        }

        console.log(this); // Output: { name: 'John' }
    
        bar();
    }

    foo();
}

const person1 = new personCreator('John');

Der lexikalische Geltungsbereich von Bar ist alles, was drinnen ist foo. Also, die Das Wert von Bar ist derjenige, der foo hat, das ist derjenige von PersonErsteller.

986860cookie-checkSind „Pfeilfunktionen“ und „Funktionen“ gleichwertig / austauschbar?

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

Privacy policy