2016-02-21 11 views
43

Da ES6 Klassen sind nur syntaktische Zucker über JavaScript bestehenden Prototyp-basierte Vererbung[1] es würde (IMO) Sinn Winde machen es Definition:Warum werden ES6-Klassen nicht gehisst?

var foo = new Foo(1, 2); //this works 

function Foo(x, y) { 
    this.x = x; 
    this.y = y; 
} 

Aber das Folgende nicht:

var foo = new Foo(1, 2); //ReferenceError 

class Foo { 
    constructor(x, y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

Warum werden ES6-Klassen nicht gehisst?

+3

ES6-Klassen * sind nicht * nur syntaktischer Zucker, obwohl sie * meist * syntaktischer Zucker sind. –

+2

Das Hochziehen war eine fast endlose Quelle von Missverständnissen und Verwirrung. Alle neuen Deklarationskonstrukte ('let',' const', 'class'), die in ES6 hinzugefügt wurden, sind nicht angehängt (nun, sie sind * halb-hiist *). Abgesehen von einem Zitat von Eich oder ähnlich, werden Sie keine Antwort bekommen, die nicht effektiv Spekulation ist. –

+0

@mmm: MDN wird von der Community bearbeitet und manchmal falsch. Nicht oft, nicht annähernd so oft wie, sagen wir, diese andere Seite, aber manchmal. Siehe [diese Antwort] (http://stackoverflow.com/a/31222689/157247) für wie sie beide gehisst und nicht gehisst werden. –

Antwort

41

Warum werden ES6-Klassen nicht gehisst?

Eigentlich sie sind gehisst (die variable Bindung in den gesamten Umfang verfügbar ist) wie let and const are - sie sind nur nicht initialisiert.

Es wäre sinnvoll, die Definition hissen

Nein. Es ist nie eine gute Idee, eine Klasse vor seiner Definition zu verwenden. Betrachten Sie das Beispiel

var foo = new Bar(); // this appears to work 
console.log(foo.x) // but doesn't 

function Bar(x) { 
    this.x = x || Bar.defaultX; 
} 
Bar.defaultX = 0; 

und vergleichen Sie es mit

var foo = new Bar(); // ReferenceError 
console.log(foo.x); 

class Bar { 
    constructor (x = Bar.defaultX) { 
     this.x = x; 
    } 
} 
Bar.defaultX = 0; 

, die einen Fehler wirft, wie man erwarten würde. Dies ist ein Problem für statische Eigenschaften, Prototyp Mixins, Dekoratoren und alles. Außerdem ist es sehr wichtig für Unterklassen, die komplett in ES5 brach, wenn Sie eine Klasse mit seinem nicht angepassten Prototyp verwendet haben, aber nun einen Fehler ausgibt, wenn eine extend Ed-Klasse noch nicht initialisiert ist.

+0

Um in Ihrem ersten Beispiel zu klären, ist das Problem, dass 'console.log (foo.x)' 'undefined' anstelle von '0' ergeben würde, nicht dass es einen Laufzeitfehler geben würde. –

3

In Javascript alle Erklärungen (var lassen, const, Funktion, Funktion *, Klasse) sind gehoben, aber es sollte in gleichen Umfang deklariert werden.

Wie Sie „ES6 Klassen sind nur syntaktischer Zucker über JavaScript bestehenden Prototyp-basierte Vererbung“, sagte

So Lassen Sie uns verstehen, was es ist?

Hier haben Sie eine Klasse deklariert, die in der Tat "spezielle Funktion" ist. Nehmen wir an, dass Ihre Funktion Foo() und Klasse Foo beide im globalen Geltungsbereich sind.

class Foo { 
    constructor(x, y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

Folgendes ist der kompilierte Code Ihrer Klasse Foo.

var Foo = (function() { 
    function Foo(x, y) { 
     this.x = x; 
     this.y = y; 
    } 
    return Foo; 
}()); 

Intern Klasse umgewandelt wird mit dem gleichen Namen in Wrapper-Funktion (IIFE) und die Wrapper-Funktion gibt Ihre Funktion zu funktionieren.

Da der (Klassen-) Bereich Ihrer Funktion geändert wird. und Sie versuchen, ein Objekt der Funktion in einem globalen Umfang zu erstellen, der in Wirklichkeit nicht existiert.

Sie erhalten die Funktion in der Variablen Foo sobald Compilation dazu kommt. Damit Sie später in var arbeiten können, können Sie ein Objekt erstellen.

+0

Während es einen ähnlichen Effekt hat, ist dies nicht, was passiert. No IIFE wird erstellt, um die Klasse zu bewerten. https://www.ecma-international.org/ecma-262/8.0/#sec-runtime-semantics-classdefinitionevaluation –

+0

wenn ich nicht falsch liege das eine life syntax (function() {}()). Wenn Sie die Klasse kompilieren, wird dieser Code generiert. Da er var zugewiesen ist, wird er nicht global aufgerufen. stattdessen wird es selbst aufgerufen und gibt den Wert an Foo zurück. –

+0

Wenn Sie etwas wie Babel verwenden, ja. Umgebungen, die Klassen nativ unterstützen, tun dies jedoch nicht. –

Verwandte Themen