Was ist der Unterschied zwischen Klassenmethode vs. Klassenfeldfunktion vs. Klassenfeldpfeilfunktion?

Lesezeit: 5 Minuten

Was ist der Unterschied zwischen Klassenmethode vs Klassenfeldfunktion vs Klassenfeldpfeilfunktion
Kombinieren

Was ist der Unterschied zwischen Klassenmethode, Klasseneigenschaft, die eine Funktion ist, und Klasseneigenschaft, die eine Pfeilfunktion ist? Hat das this Schlüsselwort verhalten sich in den verschiedenen Varianten der Methode unterschiedlich?

class Greeter {
  constructor() {
    this.greet();
    this.greet2();
    this.greet3();
  }

  greet() {
    console.log('greet1', this);
  }

  greet2 = () => {
    console.log('greet2', this);
  }

  greet3 = function() {
    console.log('greet3', this);
  }
}
      
let bla = new Greeter();

Dies ist das resultierende JavaScript, wenn es aus TypeScript transpiliert wird.

var Greeter = /** @class */ (function () {
function Greeter() {
    var _this = this;
    this.greet2 = function () {
        console.log('greet2', _this);
    };
    this.greet3 = function () {
        console.log('greet3', this);
    };
    this.greet();
    this.greet2();
    this.greet3();
}
Greeter.prototype.greet = function () {
    console.log('greet1', this);
};
return Greeter;
}());
var bla = new Greeter();

Meine TypeScript-Version ist 3.4.5.

  • Wenn ich es auf meinem Computer kompiliere, gibt es keine Fehler (tsc ./test.ts). Ich kann das kompilierte Javascript erhalten und ohne Probleme in der Browserkonsole ausführen.

    – Kombinieren

    9. Mai ’19 um 8:56


  • @Combine Nun, wenn Sie sich das Kompilierungsergebnis ansehen, sollten die Unterschiede offensichtlich sein.

    – Bergi

    9. Mai ’19 um 9:14

  • @Bergi Ich würde diese Frage nicht stellen, wenn mir die Antwort klar wäre.

    – Kombinieren

    9. Mai ’19 um 9:17

  • @Combine Hast du dir die Compilerausgabe angesehen? Kannst du es posten?

    – Bergi

    9. Mai ’19 um 9:19

  • Toll! Das sieht man jetzt greet wird auf den Prototypen gesetzt aber greet3 auf jede Instanz im Konstruktor gelegt wird, und beide verwenden dynamic this während greet2 ist eine Pfeilfunktion mit lexikalischem this.

    – Bergi

    9. Mai ’19 um 9:26

Was ist der Unterschied zwischen Klassenmethode vs Klassenfeldfunktion vs Klassenfeldpfeilfunktion
Tizian Cernicova-Dragomir

Es gibt Unterschiede zwischen allen 3 Versionen. Diese Unterschiede liegen in 3 Bereichen:

  1. Wer ist this zur Laufzeit
  2. Wo die Funktion zugewiesen ist
  3. Was ist die Art von this im Typoskript.

Fangen wir damit an, wo sie genauso funktionieren. Betrachten Sie diese Klasse mit einem Klassenfeld:

class Greeter {
  constructor(private x: string) {
  }
  greet() {
    console.log('greet1', this.x);
  }

  greet2 = () => {
    console.log('greet2', this.x);
  }

  greet3 = function () {    
    // this is typed as any 
    console.log('greet3', this.x);
  }
}

let bla = new Greeter(" me");

Mit dieser Klasse werden alle 3 Funktionsaufrufe wie erwartet gedruckt: 'greet* me' wenn aufgerufen am bla

bla.greet()
bla.greet2()
bla.greet3()

Wer ist das zur Laufzeit

Pfeilfunktionen erfassen this aus dem Deklarationskontext, also this in greet2 ist immer garantiert die Klasseninstanz, die diese Funktion erstellt hat. Die anderen Versionen (Methode und Funktion) geben keine solchen Garantien.

In diesem Code drucken also nicht alle 3 den gleichen Text:

function call(fn: () => void) {
  fn();
}

call(bla.greet) // greet1 undefined 
call(bla.greet2) //greet2 me
call(bla.greet3) // greet3 undefined

Dies ist besonders wichtig, wenn die Funktion als Ereignishandler an eine andere Komponente übergeben wird.

Wo die Funktion zugewiesen ist

Klassenmethoden (wie greet) werden auf dem Prototypen zugewiesen, Feldinitialisierungen (wie greet2 und greet3) werden im Konstruktor zugewiesen. Das bedeutet, dass greet2 und greet3 haben einen größeren Speicherbedarf, da jedes Mal eine neue Schließung zugewiesen werden muss Greeter wird instanziiert.

Was ist das für ein Typoskript.

Typoskript wird tippen this als Instanz von Greeter sowohl in der Methode (greet) und die Pfeilfunktion (greet2) aber wird tippen this wie jeder in greet3. Dies führt zu einem Fehler, wenn Sie versuchen, zu verwenden this in greet3 unter noImplictAny

Wann man sie verwendet

  1. Verwenden Sie die Methodensyntax, wenn diese Funktion nicht als Ereignishandler an eine andere Komponente übergeben wird (es sei denn, Sie verwenden bind oder etwas anderes zu gewährleisten this bleibt die Instanz der Klasse)

  2. Verwenden Sie die Syntax der Pfeilfunktion, wenn Ihre Funktion an andere Komponenten weitergegeben wird und Sie Zugriff auf . benötigen this innerhalb der Funktion.

  3. Ich kann mir keinen guten Anwendungsfall dafür vorstellen, im Allgemeinen vermeiden.

Array in Objektschlussel umwandeln duplicate
Maheer Ali

this Stichwort Unterschied:

In den oben genannten haben alle drei das gleiche this Sie werden jedoch den Unterschied sehen, wenn Sie die Methode an andere Funktionen übergeben.

class Greeter {
  constructor() {
  }
  greet() {
    console.log(this);
  }

  greet2 = () => {
    console.log(this);
  }

  greet3 = function() {
    console.log(this);
  }
}


let bla = new Greeter();
function wrapper(f){
  f();
}
wrapper(bla.greet) //undefined
wrapper(bla.greet2) //Greeter 
wrapper(bla.greet3) //undefined

Aber es gibt noch einen weiteren Unterschied, dass die erste Methode auf der prototype von class während andere zwei nicht sind. Sie sind die Methode der Objektinstanz.

class Greeter {
  constructor() {
  }
  greet() {
    console.log('greet1', this);
  }

  greet2 = () => {
    console.log('greet2', this);
  }

  greet3 = function() {
    console.log('greet3', this);
  }
}

let bla = new Greeter();
console.log(Object.getOwnPropertyNames(Greeter.prototype))

Wenn ich in der Klasse habe -> str = "my string"; und in allen 3 Methoden kann ich sagen console.log(this.str) und es gibt “my string” aus. Aber ich frage mich – ist das wirklich dasselbe?

Nein, es sind nicht dieselben Dinge. Wie ich das erwähnt habe greet2 und greet3 wird nicht eingeschaltet sein Greeter.prototype Stattdessen befinden sie sich in der Instanz selbst. Es bedeutet, dass, wenn Sie erstellen 1000 Instanzen von Greeter es werden 1000 verschiedene methoden sein (greet2 und greet3) im Speicher für 1000 verschiedene Instanzen gespeichert. Aber es wird eine einzige geben greet Methode für alle Instanzen.

Siehe das folgende Snippet mit zwei Instanzen von Greeter()

  • Wenn ich in der Klasse habe -> str = “mein String”; und in allen 3 Methoden kann ich console.log(this.str) sagen und es gibt “my string” aus. Aber ich frage mich – ist ‘das’ wirklich in allen 3 Varianten der Methode das Gleiche?

    – Kombinieren

    9. Mai ’19 um 9:03


  • @Combine Ich habe am Ende der Antwort weitere Erklärungen hinzugefügt. Überprüfen Sie bitte das.

    – Maheer Ali

    9. Mai ’19 um 9:09

  • Was meinst du, es gibt keinen Unterschied bezüglich this, Pfeilfunktionen erfassen this reguläre Funktionen nicht, große Auswirkungen, wenn Sie die Methode in einer Funktionsvariablen übergeben.

    – Tizian Cernicova-Dragomir

    9. Mai ’19 um 9:12

  • Es heißt immer noch “alle drei haben das gleiche„Was ist offensichtlich falsch?

    – Bergi

    9. Mai ’19 um 9:27

  • @Bergi Ich meine im angegebenen Code, wenn das OP die Funktion aufruft von constructor alle drei haben das gleiche this

    – Maheer Ali

    9. Mai ’19 um 9:28

.

397440cookie-checkWas ist der Unterschied zwischen Klassenmethode vs. Klassenfeldfunktion vs. Klassenfeldpfeilfunktion?

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

Privacy policy