To tłumaczenie jest niekompletne. Pomóż przetłumaczyć ten artykuł z języka angielskiego.
Klasy w Javascript zostały wprowadzone ECMAScript 2015 to lukier składniowy (ang. syntactic sugar) dla istniejącego, opartego na prototypach modelu dziedziczenia. Składnia klas nie wprowadza nowego zorientowanego obiektowo modelu dziedziczenia. Klasy wprowadzają znacznie prostszą i bardziej czytelną składnię do tworzenia obiektów i dziedziczenia.
Definiowanie klas
Klasy są w zasadzie "szczególnymi funkcjami". Pododnie jak w funkcji można definiować wyrażenie function
i deklaracje funkcji, tak składnia klasy posiada dwa komponenty: wyrażenie class
i deklaracje klasy.
Deklaracje klas
Jednym ze sposobów definiowania klas jest deklaracja klasy. Aby zadeklarować klasę, należy użyć wyrażenia class
wraz z nazwą klasy (w tym przypadku "Prostokat").
class Prostokat { constructor(wysokosc, szerokosc) { this.wysokosc = wysokosc; this.szerokosc= szerokosc; } }
Hoisting
Ważną różnicą pomiędzy deklaracją funkcji a deklaracją klasy jest to, że deklaracje funkcji są przenoszone na początek (hoisted) a klas nie. Najpierw musisz zadeklarować swoją klasę by mieć do niej dostęp, w przeciwnym razie kod, jak ten poniżej, wygeneruje wyjątek ReferenceError
:
var p = new Prostokat(); // ReferenceError class Prostokat {}
Wyrażenie class
Wyrażenie class
jest kolejnym sposobem definiowania klasy. Wyrażenia class
mogą być nazwane lub nienazwane. Nazwa przypisana nazwanemu wyrażeniu class
jest lokalna dla ciała klasy.
// nienazwane var Prostokat = class { constructor(wysokosc, szerokosc) { this.wysokosc = wysokosc; this.szerokosc = szerokosc; } }; // nazwane var Prostokat = class Prostokat { constructor(wysokosc, szerokosc) { this.wysokosc = wysokosc; this.szerokosc = szerokosc; } };
Uwaga: Wyrażenia class
dotykają te same kwestie związane z przenoszeniem na początek (ang. hoisting) co wspomnianych deklaracji klas.
Ciało klasy i definicje metod
Ciało klasy jest umieszczane w nawiasach klamrowych {}
. To tam definuje się metody, czy konstruktory.
Tryb ścisły
Ciało klasy jest wykonywane w trybie ścisłym (ang. strict mode). W celu poprawienia wydajności, kod wykorzystywany tutaj podlega scisłej składni; nie pozwala to na ukrycie niektórych wyjątków, a pewne słowa kluczowe są rezerwowane dla przyszłych wersji ECMAScript.
Konstruktor
Constructor
jest szczególną metodą, która służy tworzeniu i inicjalizowaniu obiektu zdefiniowanego słowem kluczowym class
. Dozwolony jest tylko jeden konstruktor w danej klasie. Jeśli klasa posiada więcej niż jedno wystąpienie metody constructor
, wygenerowany zostanie wyjątek SyntaxError
.
Aby wywołać konstruktor klasy bazowej, należy użyć słowa kluczowego super
.
Prototypy
Zobacz też definiowanie metod.
class Prostokat { constructor(wysokosc, szerokosc) { this.wysokosc = wysokosc; this.szerokosc = szerokosc; } get pole() { return this.liczPole(); } liczPole() { return this.wysokosc * this.szerokosc; } } const kwadrat = new Prostokat(10, 10); console.log(kwadrat.pole);
Metody statyczne
Słowo kluczowe static
definiuje metodę statyczną w klasie. Statyczne metody są wywoływane bez inicjalizowania ich klas i nie mogą być wywołane przez instancję klasy.
class Punkt { constructor(x, y) { this.x = x; this.y = y; } static odleglosc(a, b) { const dx = a.x - b.x; const dy = a.y - b.y; return Math.sqrt(dx*dx + dy*dy); } } const p1 = new Punkt(5, 5); const p2 = new Punkt(10, 10); console.log(Punkt.odleglosc(p1, p2));
Boxing with prototype and static methods
When a static or prototype method is called without an object valued "this" (or with "this" as boolean, string, number, undefined or null), then the "this" value will be undefined
inside the called function. Autoboxing will not happen. The behaviour will be the same even if we write the code in non-strict mode.
class Animal { speak() { return this; } static eat() { return this; } } let obj = new Animal(); let speak = obj.speak; speak(); // undefined let eat = Animal.eat; eat(); // undefined
If we write the above code using traditional function based classes, then autoboxing will happen based on the "this" value for which the function was called.
function Animal() { } Animal.prototype.speak = function() { return this; } Animal.eat = function() { return this; } let obj = new Animal(); let speak = obj.speak; speak(); // global object let eat = Animal.eat; eat(); // global object
Podklasy z extends
Słowo kluczowe extends
jest używane w deklaracjach klas lub wyrażeniach klas do tworzenia klasy jako elementu potomnego innej klasy.
class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } } var d = new Dog('Mitzie'); d.speak();
Jeśli w podklasie znajduje się konstruktor, musi najpierw wywołać super() przed użyciem "this".
Można również rozszerzyć tradycyjne klasy oparte na funkcjach:
function Animal (name) { this.name = name; } Animal.prototype.speak = function () { console.log(this.name + ' makes a noise.'); } class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } } var d = new Dog('Mitzie'); d.speak();
Zwróć uwagę, że klasy nie mogą rozszerzać zwykłych (niezdatnych do konstrukcji) obiektów. Jeśli chcesz dziedziczyć po zwykłym obiekcie, możesz zamiast tego użyć Object.setPrototypeOf ()
:
var Animal = { speak() { console.log(this.name + ' makes a noise.'); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal);// If you do not do this you will get a TypeError when you invoke speak var d = new Dog('Mitzie'); d.speak(); //Mitzie makes a noise.
Species
You might want to return Array
objects in your derived array class MyArray
. The species pattern lets you override default constructors.
For example, when using methods such as map()
that returns the default constructor, you want these methods to return a parent Array
object, instead of the MyArray
object. The Symbol.species
symbol lets you do this:
class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } var a = new MyArray(1,2,3); var mapped = a.map(x => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true
Super class calls with super
The super
keyword is used to call functions on an object's parent.
class Cat { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Lion extends Cat { speak() { super.speak(); console.log(this.name + ' roars.'); } }
Mix-ins
Abstract subclasses or mix-ins are templates for classes. An ECMAScript class can only have a single superclass, so multiple inheritance from tooling classes, for example, is not possible. The functionality must be provided by the superclass.
A function with a superclass as input and a subclass extending that superclass as output can be used to implement mix-ins in ECMAScript:
var calculatorMixin = Base => class extends Base { calc() { } }; var randomizerMixin = Base => class extends Base { randomize() { } };
A class that uses these mix-ins can then be written like this:
class Foo { } class Bar extends calculatorMixin(randomizerMixin(Foo)) { }
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Class definitions' in that specification. |
Standard | Initial definition. |
ECMAScript Latest Draft (ECMA-262) The definition of 'Class definitions' in that specification. |
Draft |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | Edge | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 42.0[1] 49.0 |
45 (45) | 13 | No support | No support | 9.0 |
Feature | Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|
Basic support | No support | 45.0 (45) | ? | ? | 9 | 42.0[1] 49.0 |
[1] Requires strict mode. Non-strict mode support is behind the flag "Enable Experimental JavaScript", disabled by default.