2016-03-19 18 views
5

Mit der Veröffentlichung von ECMAScript 6 im Juni 2015 wurde Javascript-Klassen-Syntax eingeführt.Javascript: Was ist der Unterschied zwischen Funktion und Klasse

Diese Syntax:

class Polygon { 
     constructor(width, height) { 
     this.width = width; 
     this.height = height; 
     } 
} 

ist im Grunde gleich wie:

function Polygon(width, height) { 
    this.width = width; 
    this.height = height; 
} 

Also, was ist der Nutzen-Klasse anstelle der traditionellen Verwendung der Funktion? Und in welchem ​​Zustand sollte ich Klasse statt Funktion verwenden?

+0

Das ist wie, 'var x = (etwas)? 1: 0' Vorteile gegenüber 'var x; if (something) {x = 1; } else {x = 0; } 'Kann Lesbarkeit sein. –

+3

Diese Antwort (obwohl kein genaues Duplikat) erklärt die Unterschiede sehr gut: http://StackOverflow.com/Questions/30783217/Why-Should-Iuse-es6-Classes – CodingIntrigue

+2

Was mit Stackoverflow falsch ist, -5 für nur Fragen normale Frage. Ich denke, das ist genug, würde ich selbst lernen. Danke für die Antwortenden, die versucht haben zu erklären, ich weiß das zu schätzen. –

Antwort

12

Es gibt einige Unterschiede zwischen Klasse und Funktion - die meisten Leute werden damit anfangen zu sagen, dass die Klasse "nur Syntax Zucker" ist, aber dass Zucker ziemlich wichtig ist. Wenn der JS-Parser den JavaScript-Code wird prosessing der Parser sie in verschiedenen AST-Knoten speichern, wie hier gezeigt, dass die ClassDeclaration und ClassExpression verschiedenen Knotentypen im Resul- AST Baum sind:

https://github.com/estree/estree/blob/master/es6.md#classes

Sie kann sehen, dass für diesen Parser führt die neuen Klassen ES6 spec eine Reihe von neuen AST Elementen der Syntax:

  • ClassBody
  • MethodDefinition
  • ClassDeclaration
  • ClassExpression
  • MetaProperty

Da die AST-Syntax nicht Standard ist, kann es mehr oder weniger Arten auf dem Parser abhängig sein, aber was ist wichtig zu bemerken, dass, wenn der Code Gibt die Klassendeklaration oder den Klassenausdruck ein, wird sie von der JavaScript-Engine anders interpretiert.

Dies bedeutet, dass Klassen- und Funktionsdeklarationen nicht ausgetauscht werden können. Sie können dies sehen, wenn Sie

class notWorking { 
    return 1; // <-- creates a parser error 
}; 

zu schreiben versuchen Dies liegt daran, wenn der Parser die Klasse -keyword trifft, wird es entweder ClassDeclaration oder ClassExpression Behandlung von den folgenden Code als ClassBody von beginnen und dann expexts es MethodDefinitions zu finden.

Dies ist ein kleines Problem, weil das Erstellen von privaten Variablen ein bisschen schwieriger wird.Die Funktionsdeklaration könnte eine private Variable ordentlich wie folgt definieren:

function myClass() { 
    var privateVar; 
} 

Die Klassendeklaration nicht haben kann:

class myClass { 
    var privateVar; // ERROR: should be a method 
} 

Dies ist, weil die Syntax der Klasse nur Methoden ermöglicht es innerhalb der Klasse deklariert werden Karosserie. Zumindest jetzt.

Allerdings gibt einen Vorschlag für die Schaffung private Felder vorhanden:

https://github.com/zenparsing/es-private-fields

So wird in der Zukunft könnten Sie in der Lage sein zu sagen,

class myClass { 
    #privateVar; // maybe this works in the future? 
} 

Es gibt eine separate Antwort auf die private Berücksichtigung Eigenschaften in ES6-Klassen, die einige Umgehungslösungen, wie die Verwendung von Symbolen vorschlagen:

Private properties in JavaScript ES6 classes

var property = Symbol(); // private property workaround example 
class Something { 
    constructor(){ 
     this[property] = "test"; 
    } 
} 

Natürlich gibt es mehr Unterschiede zwischen Klassen und Funktionen. Einer von ihnen ist Hoisting1 - im Gegensatz zu Funktionen, können Sie die Klasse überall im Umfang erklären:

Ein wichtiger Unterschied zwischen Funktionsdeklarationen und Klasse Erklärungen ist, dass Funktionsdeklarationen gehisst werden und Klasse Erklärungen sind nicht. Sie müssen zuerst Ihre Klasse deklarieren und dann darauf zugreifen

Die Klassendeklarationen und Funktionsdeklarationen sind sehr ähnlich;

function foo1() {} // can be used before declaration 
class foo2{}  // new foo2(); works only after this declaration 

Die Klasse Ausdrücke ganz ähnlich funktionieren exressions funktionieren, zum Beispiel können sie zu einer Variablen zugewiesen werden:

var myClass = class foobar {}; 

Weitere Unterschiede sind 1

  1. Die Klasse exression/Erklärung Körper wird immer in ausgeführt Strict-Modus - keine Notwendigkeit, das manuell zu spezifizieren
  2. Klassen haben ein spezielles Schlüsselwort Konstruktor - es kann nur eines von ihnen geben, oder es wird ein Fehler ausgelöst. Funktionen könnten mehrere Definitionen der Variablen der Funktion namens "Konstruktor"
  3. Klassen haben spezielle Schlüsselwort Super, die sich auf die Elternklassen Konstruktor bezieht. Wenn Sie sich innerhalb des Konstruktors befinden, können Sie super (x, y) aufrufen;, um den übergeordneten Klassenkonstruktor aufzurufen, aber innerhalb der Methode können Sie super.foobar() aufrufen, um den Aufruf einer übergeordneten Klassenfunktion zu erstellen. Diese Art von Funktionalität ist für Standardfunktionen nicht verfügbar, obwohl Sie sie möglicherweise mit einem benutzerdefinierten Hacking emulieren können.
  4. Innerhalb der Klasse Körper können Sie definieren Funktion mit statische Schlüsselwort, so dass es nur mit ClassName.FunctionName() -Syntax aufgerufen werden kann.
  5. Beide Klassendeklarationen und Ausdrücke können Tier verwenden
  6. MethodDeclaration keine Funktion -prefix benötigen, so können Sie definieren Funktion „ok“ in der Klasse „m“ wie diese erstreckt Schlüsselwörter wie Klasse Dog erweitert: Klasse m {ok() {}}. Eigentlich ist es nicht sogar als Klasse m zu definieren, erlaubt {function ok() {}}

Doch nach der Parser es ist Aufgabe abgeschlossen ist, wird die Klasseninstanz im wesentlichen die gleiche Weise wie alle anderen laufen Objekt.

Die neue ES6-Klassensyntax ist eine wesentlich klarere Art, Objekte in einer traditionellen OOP-Form auszudrücken, und wenn Sie es mögen, sollten Sie sie verwenden.

EDIT: auch die ES6 Klasse Syntax hat auch eine andere Einschränkung: Es erlaubt es nicht, die Mitgliederfunktionen lexikalisch binded zu verwenden Fett Pfeil verwenden. ES7 scheint experimental feature zu haben, was es erlaubt. Das kann zum Beispiel nützlich sein, wenn Methoden an Event-Handler gebunden werden, die zugehörige Frage lautet here.

1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

+0

Danke für die Erklärung und Referenzen, hilft sehr. –

+0

Ich habe auch einen Hinweis auf die fehlende Fettpfeilsyntax für die ES6-Klasse-Deklaration hinzugefügt. –

+0

@TeroTolonen: Das ist kaum ein "Feature", das Klassen von Funktionen unterscheidet. Sie können Pfeilfunktionen innerhalb des Konstruktors und nicht auf dem Prototyp verwenden. – Bergi

0

class es ist nichts als eine syntaktische Zucker über Javascript Logik Klassenerstellung mit function. Wenn Sie einen function als class verwenden, fungiert die gesamte Funktion als Konstruktor, wenn Sie andere Memberfunktionen in Konstruktoren wie this.something = ... oder var something = ... im Falle von privaten Mitgliedern setzen möchten (wenn Sie nicht von außen injizieren) Angenommen, Sie erstellen ein Objekt mit anderen Methoden/Eigenschaften), aber im Falle einer Klasse ist die gesamte Funktion nicht tatsächlich ein Konstruktor, sondern Sie können ihn explizit mit anderen Elementfunktionen und Daten trennen.

Verwandte Themen