it-swarm.com.de

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

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;
};

Prototyp-Methoden

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

// vs

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

Objekt (wörtlich) 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) => {
  // ...
};
412
Felix Kling

tl; dr: Nein! Pfeilfunktionen und Funktionsdeklarationen/-ausdrücke sind nicht gleichwertig und kann nicht blind ersetzt werden.
Wenn die zu ersetzende Funktion nicht this, arguments verwendet und nicht mit new aufgerufen wird, dann Ja.


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

1. Lexikalisch this und arguments

Pfeilfunktionen haben keine eigene this oder arguments Bindung. Stattdessen werden diese Bezeichner wie jede andere Variable im lexikalischen Bereich aufgelöst. Das heißt, innerhalb einer Pfeilfunktion beziehen sich this und arguments auf die Werte von this und arguments in der Umgebung, in der die Pfeilfunktion definiert ist 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 Funktionsausdrucksfall bezieht sich this auf das Objekt, das innerhalb von createObject erstellt wurde. In dem Pfeilfunktionsfall bezieht sich this auf this von createObject selbst.

Dies macht Pfeilfunktionen nützlich, wenn Sie auf this der aktuellen 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 nicht möglich ist, die this einer Pfeilfunktion mit einzustellen .bind oder .call.

Wenn Sie mit this nicht sehr vertraut sind, sollten Sie es lesen

2. Pfeilfunktionen können nicht mit new aufgerufen werden

ES2015 unterscheidet zwischen Funktionen, die aufrufen können, und Funktionen, die konstruieren können. Wenn eine Funktion konstruierbar ist, kann sie mit new, d. H. new User(), aufgerufen werden. Wenn eine Funktion aufrufbar ist, kann sie ohne new (d. H. Normalen Funktionsaufruf) aufgerufen werden.

Funktionen, die durch Funktionsdeklarationen/-ausdrücke erstellt wurden, 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 aufrufbare Funktion zu erstellen, wird ein Laufzeitfehler angezeigt.


Wenn wir das wissen, können wir folgendes sagen.

Austauschbar:

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

Nicht austauschbar:

  • Konstruktorfunktionen
  • Zu einem Prototyp hinzugefügte Funktion/Methoden (da sie normalerweise this verwenden)
  • Variadische Funktionen (wenn sie arguments verwenden (siehe unten))

Schauen wir uns das anhand Ihrer Beispiele genauer an:

Konstruktorfunktion

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

Prototypmethoden

Höchstwahrscheinlich nicht, da Prototypmethoden normalerweise this verwenden, um auf die Instanz zuzugreifen. Wenn sie this nicht verwenden, können Sie es ersetzen. Wenn Sie jedoch in erster Linie auf kurze Syntax Wert legen, verwenden Sie class mit seiner kurzen Methodensyntax:

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

  getName() {
    return this.name;
  }
}

Objektmethoden

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

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

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

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

Variadische Funktionen

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

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

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

Verwandte Frage:

Weitere Ressourcen:

625
Felix Kling

Schauen Sie sich dieses Beispiel an

Die Variable this ist sehr unterschiedlich timesCalled wird bei jedem Tastendruck nur um 1 erhöht. Welche Antworten meine persönliche Frage:

.click( () => { } )

und

.click(function() { })

Beide erzeugen die gleiche Anzahl von Funktionen, wenn sie in einer Schleife verwendet werden, wie Sie an der Guid-Anzahl im Plnkr sehen können.

3
abbaf33f