Sind 'Pfeilfunktionen' und 'Funktionen' gleichwertig / austauschbar?

Dec 19 2015

Pfeilfunktionen in ES2015 bieten eine präzisere 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;
};

Prototypmethoden

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

// vs

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

Objektmethoden (Literalmethoden)

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) => {
  // ...
};

Antworten

817 FelixKling Dec 19 2015 at 00:58

tl; dr: Nein! Pfeilfunktionen und Funktionsdeklarationen / -ausdrücke sind nicht äquivalent und können nicht blind ersetzt werden.
Wenn die Funktion, die Sie ersetzen möchten, nicht verwendet thiswird argumentsund nicht mit aufgerufen wird new, dann ja.


Wie so oft: es kommt darauf an . Pfeilfunktionen haben ein anderes Verhalten als Funktionsdeklarationen / -ausdrücke. Schauen wir uns also zuerst die Unterschiede an:

1. Lexikalisch thisundarguments

Pfeilfunktionen haben keine eigene thisoder argumentsBindung. Stattdessen werden diese Bezeichner wie jede andere Variable im lexikalischen Bereich aufgelöst. Das bedeutet, dass innerhalb einer Pfeilfunktion thisund unter argumentsBezugnahme auf die Werte von thisund argumentsin der Umgebung die Pfeilfunktion definiert ist (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

thisBezieht sich im Fall des Funktionsausdrucks auf das Objekt, das innerhalb des Objekts erstellt wurde createObject. In Pfeil Funktion Fall thisbezieht sich auf thisvon createObjectselbst.

Dies macht Pfeilfunktionen nützlich, wenn Sie auf thisdie aktuelle Umgebung zugreifen müssen :

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

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

Beachten Sie, dass dies auch bedeutet, dass es nicht möglich ist, eine Pfeilfunktion thismit .bindoder festzulegen .call.

Wenn Sie nicht sehr vertraut sind this, lesen Sie

2. Pfeilfunktionen können nicht mit aufgerufen werden new

ES2015 unterscheidet zwischen Funktionen, die aufrufbar sind , und Funktionen, die konstruierbar sind . Wenn eine Funktion konstruierbar ist, kann sie mit aufgerufen werden new, d new User(). H. Wenn eine Funktion aufrufbar ist, kann sie ohne aufgerufen werden new(dh normaler Funktionsaufruf).

Durch Funktionsdeklarationen / -ausdrücke erstellte Funktionen sind sowohl konstruierbar als auch aufrufbar.
Pfeilfunktionen (und Methoden) können nur aufgerufen werden. classKonstruktoren sind nur konstruierbar.

Wenn Sie versuchen, eine nicht aufrufbare Funktion aufzurufen oder eine nicht aufbaubare Funktion zu erstellen, wird ein Laufzeitfehler angezeigt.


In diesem Wissen können wir Folgendes feststellen.

Austauschbar:

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

Nicht austauschbar:

  • Konstruktorfunktionen
  • Funktion / Methoden, die einem Prototyp hinzugefügt wurden (weil sie normalerweise verwendet werden this)
  • Variadische Funktionen (falls verwendet arguments(siehe unten))

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 Funktionsausdruck oder verwenden Sie class.

Prototypmethoden

Höchstwahrscheinlich nicht, da Prototypmethoden normalerweise thisfür den Zugriff auf die Instanz verwendet werden. Wenn sie nicht verwenden this, können Sie es ersetzen. Wenn Sie sich jedoch hauptsächlich für eine prägnante Syntax interessieren, verwenden Sie diese classmit ihrer prägnanten Methodensyntax:

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

Objektmethoden

Ähnliches gilt für Methoden in einem Objektliteral. Wenn die Methode auf das Objekt selbst verweisen möchte this, verwenden 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 Aliasing verwenden thisoder Folgendes verwenden .bind(this):

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

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

Aber: Wenn der Code, der den Rückruf aufruft, explizit thisauf einen bestimmten Wert festgelegt wird, wie dies häufig bei Ereignishandlern, insbesondere bei jQuery, der Fall ist und der Rückruf this(oder arguments) verwendet, können Sie keine Pfeilfunktion verwenden !

Variadische Funktionen

Da Pfeilfunktionen keine eigenen haben arguments, können Sie sie nicht einfach durch eine Pfeilfunktion ersetzen. ES2015 bietet jedoch eine Alternative zur Verwendung arguments: den Parameter rest .

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

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

Verwandte Frage:

Weitere Ressourcen:

17 Ashutosh Jan 10 2020 at 03:22

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

Warten Sie, Sie können die Pfeilfunktion nicht überall in Ihrem Code verwenden. Sie funktioniert nicht in allen Fällen, in thisdenen Pfeilfunktionen nicht verwendet werden können. Ohne Zweifel ist die Pfeilfunktion eine großartige Ergänzung, die Code-Einfachheit bringt.

Sie können jedoch keine Pfeilfunktion verwenden, wenn ein dynamischer Kontext erforderlich ist: Definieren von Methoden, Erstellen von Objekten mit Konstruktoren, Abrufen des Ziels beim Behandeln von Ereignissen.

Pfeilfunktionen sollten NICHT verwendet werden, weil:

  1. Sie haben nicht this

    Es verwendet "lexikalisches Scoping", um herauszufinden, wie hoch der Wert von " this" sein sollte. In lexikalischem Scoping mit einfachen Worten wird " this" aus dem Inneren des Funktionskörpers verwendet.

  2. Sie haben nicht arguments

    Pfeilfunktionen haben kein argumentsObjekt. Die gleiche Funktionalität kann jedoch mit Ruheparametern 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 Construtoren sein, da sie keine Prototyp-Eigenschaft haben.

Wann und wann nicht?

  1. Verwenden Sie diese Option nicht, um eine Funktion als Eigenschaft im Objektliteral hinzuzufügen, da wir nicht darauf zugreifen können.
  2. Funktionsausdrücke eignen sich am besten für Objektmethoden. Pfeil Funktionen sind am besten für Rückrufe oder Methoden wie map, reduceoder forEach.
  3. Verwenden Sie Funktionsdeklarationen für Funktionen, die Sie beim Namen aufrufen möchten (weil sie hochgezogen sind).
  4. Verwenden Sie Pfeilfunktionen für Rückrufe (da diese tendenziell kürzer sind).
2 toddmo May 16 2020 at 08:56

Um Pfeilfunktionen mit zu verwenden function.prototype.call, habe 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);
  }

Verwendung

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

Bearbeiten

Du brauchst keinen Helfer. Du könntest es tun:

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