From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../pl/web/javascript/reference/classes/index.html | 410 +++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 files/pl/web/javascript/reference/classes/index.html (limited to 'files/pl/web/javascript/reference/classes/index.html') diff --git a/files/pl/web/javascript/reference/classes/index.html b/files/pl/web/javascript/reference/classes/index.html new file mode 100644 index 0000000000..81388acbc3 --- /dev/null +++ b/files/pl/web/javascript/reference/classes/index.html @@ -0,0 +1,410 @@ +--- +title: Classes +slug: Web/JavaScript/Reference/Classes +tags: + - Classes + - Constructors + - ECMAScript 2015 + - Inheritance + - Intermediate + - JavaScript + - TopicStub +translation_of: Web/JavaScript/Reference/Classes +--- +
{{JsSidebar("Classes")}}
+ +

Klasy w Javascript zostały wprowadzone w ECMAScript 2015 jako 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". Podobnie 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ć słowa kluczowego 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 ({{Glossary("Hoisting")}}) a klas nie. Najpierw musisz zadeklarować swoją klasę, by mieć do niej dostęp, w przeciwnym razie kod, jak ten poniżej, wygeneruje błąd {{jsxref("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. (można ją odczytać z właściwości {{jsxref("Function.name", "name")}} klasy)

+ +
// nienazwane
+var Prostokat = class {
+  constructor(wysokosc, szerokosc) {
+    this.wysokosc = wysokosc;
+    this.szerokosc = szerokosc;
+  }
+};
+console.log(Prostokat.name); // Prostokat
+
+// nazwane
+var Prostokat = class Prostokat2 {
+  constructor(wysokosc, szerokosc) {
+    this.wysokosc = wysokosc;
+    this.szerokosc = szerokosc;
+  }
+};
+console.log(Prostokat.name); // Prostokat2
+
+ +
+

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 definiuje 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 ścisł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 błąd {{jsxref("SyntaxError")}}.

+ +

Aby wywołać konstruktor klasy bazowej, należy użyć słowa kluczowego super.

+ +

Metody

+ +

Zobacz też definiowanie metod.

+ +
class Prostokat {
+  constructor(wysokosc, szerokosc) {
+    this.wysokosc = wysokosc;
+    this.szerokosc = szerokosc;
+  }
+  // Getter
+  get pole() {
+    return this.liczPole();
+  }
+  // Method
+  liczPole() {
+    return this.wysokosc * this.szerokosc;
+  }
+}
+
+const kwadrat = new Prostokat(10, 10);
+
+console.log(kwadrat.pole); // 100
+ +

Metody i właściwości statyczne

+ +

Słowo kluczowe static definiuje metodę kub właściwość statyczną w klasie. Statyczne metody i właściwości 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 nazwa = "Punkt";
+  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);
+p1.nazwa; // undefined
+p1.odleglosc; // undefined
+p2.nazwa; // undefined
+p2.odleglosc; // undefined
+
+console.log(Punkt.nazwa); // "Punkt"
+console.log(Punkt.odleglosc(p1, p2)); // 7.0710678118654755
+ +

Powiązanie this z metodami niestatycznymi i statycznymi

+ +

Kiedy metoda typu static lub prototype jest wywoływana bez this (na przykład poprzez przypisanie metody do zmiennej), wtedy this będzie undefined w środku metody. Takie zachowanie będzie takie same, nawet jeżeli dyrektywa "use strict" nie będzie obecna, ponieważ kod w obrębie metody danej klasy zawsze będzie wykonywał się jako strict mode.

+ +
class Animal {
+  speak() {
+    return this;
+  }
+  static eat() {
+    return this;
+  }
+}
+
+let obj = new Animal();
+obj.speak(); // obiekt Animal
+let speak = obj.speak;
+speak(); // undefined
+
+Animal.eat(); // klasa Animal
+let eat = Animal.eat;
+eat(); // undefined
+ +

Jeśli przepiszemy powyższy przykład z użyciem tradycyjnych funkcji bez dyrektywy "use strict", to this wywołane w metodzie będzie automatycznie przypisane do pierwotnej wartości this, którą domyślnie jest global object.

+ +
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
+
+ +

Właściwości instancji

+ +

Właściwości instancji muszą być zdefiniowane wewnątrz metody klasy:

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

Statyczne właściwości i właściwości prototypu muszą być zdefiniowane poza ciałem klasy:

+ +
Rectangle.staticWidth = 20;
+Rectangle.prototype.prototypeWidth = 25;
+ +

Deklaracje pól

+ +
+

Publiczna i prywatne deklaracje pól są funkcjonalnościami eksperymentalnymi zaproponowanymi na TC39. Wsparcie przeglądarek jest ograniczone, ale ta funkcjonalność może być używana przy użyciu systemów takich jak Babel

+
+ +

Deklaracje pól publicznych

+ +

Przy użyciu deklaracji pól, powyższy przykład może być przepisany na:

+ +
class Rectangle {
+  height = 0;
+  width;
+  constructor(height, width) {
+    this.height = height;
+    this.width = width;
+  }
+}
+
+ +

Dzięki deklarowaniu pól na początku klasy, definicje klas stają się bardziej samodokumentujące, a pola są zawsze obecne.

+ +

Jak widać w powyższym przykładzie, pola mogą być zadeklarowane z lub bez domyślnej wartości.

+ +

Zobacz public class fields po więcej informacji.

+ +

Deklaracje pól prywatnych

+ +

Używając deklaracji pól prywatnych, definicja może być zapisana w taki sposób:

+ +
class Rectangle {
+  #height = 0;
+  #width;
+  constructor(height, width) {
+    this.#height = height;
+    this.#width = width;
+  }
+}
+
+ +

Próba odniesienia się do prywatnego pola poza ciałem klasy wygeneruje błąd. Prywatne pola mogą być tylko odczytywane i modyfikowane wewnątrz ciała klasy. Poprzez definicję właściwości niewidocznych poza ciałem klasy, można zapewnić, że użytkownicy klasy nie będą polegali na jej wewnętrznych właściwościach.

+ +
+

Pola prywatne mogą być tylko zadeklarowane na początku ciała klasy

+
+ +

Prywatnych pól nie da się utworzyć później, poprzez przypisywanie, tak jak normalnych właściwości.

+ +

Po więcej informacji zobacz private class fields.

+ +

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 {
+  constructor(name) {
+    super(name); // wywyłanie konstruktora klasy nadrzędnej poprzez użycie super()
+  }
+  speak() {
+    console.log(this.name + ' barks.');
+  }
+}
+
+let d = new Dog('Mitzie');
+d.speak(); // Mitzie barks.
+
+ +

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.');
+  }
+}
+
+let d = new Dog('Mitzie');
+d.speak(); // Mitzie barks
+
+ +

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ć {{jsxref ("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
+
+let d = new Dog('Mitzie');
+d.speak(); //Mitzie makes a noise.
+
+ +

Species

+ +

Jeśli chcesz zwrócić obiekt {{jsxref("Array")}} w twojej klasie MyArray, która dziedziczy po Array, to możesz użyć wzorca "species", który pozwala na nadpisywanie domyślnych konstruktorów.

+ +

Na przykład, wywołanie metody {{jsxref("Array.map", "map()")}} zwraca domyślny konstruktor MyArray. Użycie {{jsxref("Symbol.species")}} pozwala na nadpisanie tego zachowania tak, by zwracany był obiekt typu Array, a nie MyArray:

+ +
class MyArray extends Array {
+  // Nadpisanie domyślnego kontruktora
+  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
+
+ +

Słowo kluczowe super

+ +

Słowo kluczowe super jest wykorzystywane do udostępniania i korzystania z funkcji klasy, po której nasz obiekt dziedziczy.

+ +
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.`);
+  }
+}
+
+let l = new Lion('Fuzzy');
+l.speak();
+// Fuzzy makes a noise.
+// Fuzzy roars.
+ +

Mix-ins

+ +

Abstrakcyjne podklasy lub mix-ins są szablonami dla klas. Klasa może mieć tylko jedną klasę nadrzędną, więc dziedziczenie z wielu klas jest niemożliwe. Cała funkcjonalność musi być dostarczona przez jedną klasę nadrzędną.

+ +

Funkcja przyjmująca klasę nadrzędną jako argument i zwracająca podklasę rozszerzającą klasę nadrzędną może być użyta do implementacji mix-in'ów:

+ +
var calculatorMixin = Base => class extends Base {
+  calc() { }
+};
+
+var randomizerMixin = Base => class extends Base {
+  randomize() { }
+};
+
+ +

Klasa używająca tych mix-in'ów może być zapisana w taki sposób:

+ +
class Foo { }
+class Bar extends calculatorMixin(randomizerMixin(Foo)) { }
+ +

Specyfikacje

+ + + + + + + + + + + + + + + + + + + +
SpecyfikacjaStatusKomentarz
{{SpecName('ES2015', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ES2015')}}Initial definition.
{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ESDraft')}}
+ +

Kompatybilność

+ +

{{Compat("javascript.classes")}}

+ +

Zobacz też

+ + -- cgit v1.2.3-54-g00ecf