From 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:43:23 -0500 Subject: initial commit --- .../reference/classes/constructor/index.html | 119 ++++++ .../reference/classes/extends/index.html | 112 ++++++ .../uk/web/javascript/reference/classes/index.html | 418 +++++++++++++++++++++ .../javascript/reference/classes/static/index.html | 137 +++++++ 4 files changed, 786 insertions(+) create mode 100644 files/uk/web/javascript/reference/classes/constructor/index.html create mode 100644 files/uk/web/javascript/reference/classes/extends/index.html create mode 100644 files/uk/web/javascript/reference/classes/index.html create mode 100644 files/uk/web/javascript/reference/classes/static/index.html (limited to 'files/uk/web/javascript/reference/classes') diff --git a/files/uk/web/javascript/reference/classes/constructor/index.html b/files/uk/web/javascript/reference/classes/constructor/index.html new file mode 100644 index 0000000000..488a9c1829 --- /dev/null +++ b/files/uk/web/javascript/reference/classes/constructor/index.html @@ -0,0 +1,119 @@ +--- +title: Конструктор +slug: Web/JavaScript/Reference/Classes/constructor +tags: + - Classes + - ECMAScript6 + - JavaScript +translation_of: Web/JavaScript/Reference/Classes/constructor +--- +
{{jsSidebar("Classes")}}
+ +

Метод constructor — це особливий метод, призначений для створення й започаткування (ініціалізації) новоствореного примірника класу.

+ +

Синтаксис

+ +
constructor([аргументи]) { … }
+ +

Опис

+ +

Клас може мати лише один метод з іменем «constructor». Спроба оголосити декілька методів «constructor» для одного класу матиме наслідком помилку {{jsxref("Global_Objects/SyntaxError", "SyntaxError")}}.

+ +

Метод constructor може звернутися до однойменного методу батьківського класу (надкласу) через ключове слово {{jsxref("Operators/super", "super")}}.

+ +

За відсутності оголошеного методу constructor буде використано типовий започаткувач (конструктор).

+ +

Приклади

+ +

Використання методу constructor

+ +

Цей шмат коду взято з classes sample (переглянути наживо):

+ +
class Square extends Polygon {
+  constructor(length) {
+    // Наступний рядок здійснює виклик успадкованого від Polygon
+    // конструктора, передаючи до нього власні параметри.
+    super(length, length);
+
+    // Завважте, що в класах-нащадках виклик super() завжди має передувати
+    // найпершому звертанню до this. Інакше матимете помилку.
+    this.name = 'Square';
+  }
+
+  get area() {
+    return this.height * this.width;
+  }
+
+  set area(value) {
+    this.area = value;
+  }
+}
+ +

Інший приклад

+ +

Погляньте також на цей приклад:

+ +
class Polygon {
+    constructor() {
+        this.name = "Polygon";
+    }
+}
+
+class Square extends Polygon {
+    constructor() {
+        super();
+    }
+}
+
+let newInstance = new Square();
+console.log(newInstance.name);  // виводить "Polygon"
+ +

Типові конструктори

+ +

Якщо метод constructor не оголошено, буде використано типовий конструктор. Для первинного класу (що не успадковує інших) то є метод з порожнім тілом:

+ +
constructor() {}
+
+ +

Натомість для вторинного класу (що успадковує якийсь інший клас) типовим конструктором є такий:

+ +
constructor(...args) {
+  super(...args);
+}
+ +

Специфікації

+ + + + + + + + + + + + + + + + + + + +
СпецифікаціяСтатусКоментар
{{SpecName('ES6', '#sec-static-semantics-constructormethod', 'Constructor Method')}}{{Spec2('ES6')}}Первинне визначення.
{{SpecName('ESDraft', '#sec-static-semantics-constructormethod', 'Constructor Method')}}{{Spec2('ESDraft')}} 
+ +

Підтримка веб-переглядачами

+ + + +

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

+ +

Див. також

+ + diff --git a/files/uk/web/javascript/reference/classes/extends/index.html b/files/uk/web/javascript/reference/classes/extends/index.html new file mode 100644 index 0000000000..fb64cf21aa --- /dev/null +++ b/files/uk/web/javascript/reference/classes/extends/index.html @@ -0,0 +1,112 @@ +--- +title: extends +slug: Web/JavaScript/Reference/Classes/extends +tags: + - ECMAScript 2015 + - JavaScript + - Класи +translation_of: Web/JavaScript/Reference/Classes/extends +--- +
{{jsSidebar("Classes")}}
+ +

Ключове слово extends використовується у оголошеннях класів або у виразах класів для створення дочірнього класу від іншого класу.

+ +
{{EmbedInteractiveExample("pages/js/classes-extends.html", "taller")}}
+ + + +

Синтаксис

+ +
class ChildClass extends ParentClass { ... }
+ +

Опис

+ +

Ключове слово extends може використовуватись для створення підкласів з користувацьких класів, як і з вбудованих об'єктів.

+ +

Значенням .prototype батьківського класу має бути {{jsxref("Object")}} або {{jsxref("null")}}.

+ +

Приклади

+ +

Використання extends

+ +

Перший приклад створює клас на ім'я Square (квадрат) з класу на ім'я Polygon (багатокутник). Даний приклад взятий з цього зразка (джерело).

+ +
class Square extends Polygon {
+  constructor(length) {
+    // Тут він викликає конструктор батьківського класу
+    // та надає значення ширини й довжини багатокутника
+    super(length, length);
+    // Заувага: У похідному класі super() має викликатися до
+    // використання 'this'. Інакше виникне помилка посилання.
+    this.name = 'Square';
+  }
+
+  get area() {
+    return this.height * this.width;
+  }
+}
+ +

Використання extends із вбудованими об'єктами

+ +

Цей приклад розширює вбудований об'єкт {{jsxref("Date")}}. Даний приклад взяти з цього зразка (джерело).

+ +
class myDate extends Date {
+  constructor() {
+    super();
+  }
+
+  getFormattedDate() {
+    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+    return this.getDate() + '-' + months[this.getMonth()] + '-' + this.getFullYear();
+  }
+}
+ +

Розширення null

+ +

Розширення {{jsxref("null")}} працює, як для звичайних класів, за винятком того, що прототип не успадковується від {{jsxref("Object.prototype")}}.

+ +
class nullExtends extends null {
+  constructor() {}
+}
+
+Object.getPrototypeOf(nullExtends); // Function.prototype
+Object.getPrototypeOf(nullExtends.prototype) // null
+
+new nullExtends(); //ReferenceError: this is not defined
+
+ +

Специфікації

+ + + + + + + + + + + + + + + + + + + +
СпецифікаціяСтатусКоментар
{{SpecName('ES2015', '#sec-class-definitions', 'extends')}}{{Spec2('ES2015')}}Початкове визначення.
{{SpecName('ESDraft', '#sec-class-definitions', 'extends')}}{{Spec2('ESDraft')}}
+ +

Сумісність з веб-переглядачами

+ + + +

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

+ +

Див. також

+ + diff --git a/files/uk/web/javascript/reference/classes/index.html b/files/uk/web/javascript/reference/classes/index.html new file mode 100644 index 0000000000..ec1694bfd1 --- /dev/null +++ b/files/uk/web/javascript/reference/classes/index.html @@ -0,0 +1,418 @@ +--- +title: Класи +slug: Web/JavaScript/Reference/Classes +tags: + - ECMAScript 2015 + - JavaScript + - Класи + - конструктори + - наслідування +translation_of: Web/JavaScript/Reference/Classes +--- +
{{JsSidebar("Classes")}}
+ +

Класи в JavaScript були додані в стандарті ECMAScript 6 і є насамперед синтаксичним цукром для існуючого прототипного наслідування у JavaScript. Синтаксис класів не впроваджує нову модель об'єктно-орієнтованого наслідування у JavaScript.

+ +

Визначення класів

+ +

Класи - це, по факту, "особливі функції", і так само, як ви можете визначити функціональний вираз та оголошення функції, синтаксис класу складається з двох компонентів: виразу класу and оголошення класу.

+ +

Оголошення класу

+ +

Одним зі способів визначення класу є оголошення класу. Для оголошення класу використовується ключове слово class з назвою класу (у прикладі нижче "Rectangle").

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

Підняття

+ +

Важлива відмінність між оголошеннями функції та класу полягає в тому, що оголошення функції {{Glossary("Hoisting", "піднімається")}}, а оголошення класу ні. Спочатку необхідно оголосити клас, і тільки потім звертатись до нього, інакше подібний код викине помилку {{jsxref("ReferenceError")}}:

+ +
const p = new Rectangle(); // ReferenceError
+
+class Rectangle {}
+
+ +

Вираз класу

+ +

Вираз класу - це інший спосіб визначення класу. Вираз класу може бути іменованим або неіменованим. Ім'я, надане іменованому виразу класу, є локальним для тіла класу. (Хоча його можна отримати через властивість класу (не екземпляра) {{jsxref("Function.name", "name")}}).

+ +
// не іменований
+let Rectangle = class {
+  constructor(height, width) {
+    this.height = height;
+    this.width = width;
+  }
+};
+console.log(Rectangle.name);
+// виведе "Rectangle"
+
+// іменований
+let Rectangle = class Rectangle2 {
+  constructor(height, width) {
+    this.height = height;
+    this.width = width;
+  }
+};
+console.log(Rectangle.name);
+// виведе "Rectangle2"
+
+ +
+

Заувага: Вирази класів підпадають під такі самі обмеження підняття, які описані у розділі {{anch("Оголошення класу")}}.

+
+ +

Тіло класу та визначення методів

+ +

Тіло класу - це та частина, що знаходиться у фігурних дужках {}. Тут ви визначаєте складові класу, такі як методи або конструктор.

+ +

Строгий режим

+ +

Код у тілі класу виконується у строгому режимі, тобто, код, записаний тут, є предметом більш строгого синтаксису заради підвищення продуктивності. Деякі помилки, які пройшли б непоміченими, будуть викидатися, а певні ключові слова є зарезервованими для майбутніх версій ECMAScript.

+ +

Конструктор

+ +

Метод constructor - це спеціальний метод для створення та ініціалізації об'єктів, створених ключовим словом class. У класі може бути лише один спеціальний метод з ім'ям "constructor". Якщо клас містить більше одного метода constructor, виникне помилка {{jsxref("SyntaxError")}}.

+ +

Конструктор може звертатися до конструктора батьківського класу за допомогою ключового слова super.

+ +

Методи прототипу

+ +

Дивіться також визначення методів

+ +
class Rectangle {
+  constructor(height, width) {
+    this.height = height;
+    this.width = width;
+  }
+  // гетер
+  get area() {
+    return this.calcArea();
+  }
+  // метод
+  calcArea() {
+    return this.height * this.width;
+  }
+}
+
+const square = new Rectangle(10, 10);
+
+console.log(square.area); // 100
+ +

Статичні методи

+ +

Ключове слово static визначає статичний метод класу. Статичні методи класу викликаються без створення екземпляра свого класу і не можуть бути викликані через екземпляр класу. Статичні методи часто використовують для створеня функцій-утиліт для застосунків.

+ +
class Point {
+    constructor(x, y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    static distance(a, b) {
+        const dx = a.x - b.x;
+        const dy = a.y - b.y;
+
+        return Math.hypot(dx, dy);
+    }
+}
+
+const p1 = new Point(5, 5);
+const p2 = new Point(10, 10);
+p1.distance; //undefined
+p2.distance; //undefined
+
+console.log(Point.distance(p1, p2)); // 7.0710678118654755
+ +

Пакування через прототипні та статичні методи

+ +

Коли статичний або прототипний метод викликається без значення для this, значенням this всередині метода буде undefined. Ця поведінка буде такою самою навіть якщо директива "use strict" не задана, тому що код в межах тіла класу завжди виконується у строгому режимі.

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

Якщо наведений приклад написаний з використанням традиційного синтаксису функцій, то автоматичне пакування при викликах методів відбуватиметься у нестрогому режимі, на основі початкового значення this. Якщо початковим значенням є undefinedthis буде присвоєний глобальний об'єкт.

+ +

Автопакування не відбудеться у строгому режимі, значення this залишиться незмінним.

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

Властивості екземпляра

+ +

Властивості екземпляра повинні визначатися всередині методів класу:

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

Статичні (на боці класу) властивості-значення та прототипні властивості-значення повинні визначатися за межами оголошення класу:

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

Оголошення полів класу

+ +
+

Оголошення публічних та приватних полів є експериментальною функціональністю (stage 3), запропонованою на TC39, комітеті стандартів JavaScript. Підтримка у переглядачах є обмеженою, але функціональність можна використовувати через збирачі пакетів з системами на кшталт Babel.

+
+ +

Оголошення публічних полів

+ +

З синтаксисом оголошення полів JavaScript наведений вище приклад можна записати наступним чином:

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

З оголошенням полів заздалегідь оголошення класу стає більш самозадокументованим, а поля завжди присутні.

+ +

Як бачимо, оголошені поля можуть мати або не мати значення за замовчуванням.

+ +

Оголошення приватних полів

+ +

З використанням приватних полів визначення можна вдосконалити наступним чином.

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

Буде помилкою посилатися на приватні поля поза межами класу; вони доступні для читання або запису тільки всередині тіла класу. Визначаючи щось, невидиме за межами класу, ви забезпечуєте умови, за яких користувачі ваших класів не зможуть покладатися на внутрішні властивості, які можуть змінюватись між версіями.

+ +

Приватні поля можуть оголошуватися лише одразу при оголошенні полів.

+ +

Приватні поля не можуть створюватись пізніше через присвоювання, як це роблять нормальні властивості.

+ +

Щоб дізнатись більше, дивіться також поля класу.

+ +

Створення підкласу за допомогою extends

+ +

Ключове слово extends використовують у оголошенні класу або у виразі класу, щоб створити клас, як дочірній від іншого класу.

+ +
class Animal {
+  constructor(name) {
+    this.name = name;
+  }
+
+  speak() {
+    console.log(`${this.name} видає звуки.`);
+  }
+}
+
+class Dog extends Animal {
+  constructor(name) {
+    super(name); // викликати конструктор суперкласу та передати параметром ім'я
+  }
+
+  speak() {
+    console.log(`${this.name} гавкає.`);
+  }
+}
+
+let d = new Dog('Мінні');
+d.speak(); // Мінні гавкає.
+ +

Якщо у підкласі присутній конструктор, він має спочатку викликати super(), перед використанням "this".

+ +

Можна також розширювати через extend традиційні "класи" на основі функцій:

+ +
function Animal (name) {
+  this.name = name;
+}
+
+Animal.prototype.speak = function () {
+  console.log(`${this.name} видає звуки.`);
+}
+
+class Dog extends Animal {
+  speak() {
+    console.log(`${this.name} гавкає.`);
+  }
+}
+
+let d = new Dog('Мінні');
+d.speak(); // Мінні гавкає.
+
+//Заувага: Для однойменних методів, дочірній метод переважає над батьківським
+ +

Зауважте, що класи не можуть розширювати звичайні об'єкти (не конструктори). Якщо бажаєте успадкуватись від звичайного об'єкта, можете натомість використати {{jsxref("Object.setPrototypeOf()")}}:

+ +
const Animal = {
+  speak() {
+    console.log(`${this.name} видає звуки.`);
+  }
+};
+
+class Dog {
+  constructor(name) {
+    this.name = name;
+  }
+}
+
+// Якщо ви цього не зробите, то отримаєте помилку, викликавши speak
+Object.setPrototypeOf(Dog.prototype, Animal);
+
+let d = new Dog('Мінні');
+d.speak(); // Мінні видає звуки.
+ +

Species

+ +

Можливо, ви захочете повернути об'єкти {{jsxref("Array")}} у своєму похідному класі масиву MyArray. Шаблон species дозволяє перевизначати початкові конструктори.

+ +

Наприклад, використовуючи такі методи, як {{jsxref("Array.map", "map()")}}, що повертає конструктор за замовчуванням, ви хочете, щоб ці методи повертали батьківський об'єкт Array замість об'єкту MyArray. Символ {{jsxref("Symbol.species")}} дозволяє це зробити:

+ +
class MyArray extends Array {
+  // Заміщення Symbol.species батьківським конструктором Array
+  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

+ +

Ключове слово super використовують для виклику відповідних методів суперкласу. Це одна з переваг над прототипним наслідуванням.

+ +
class Cat {
+  constructor(name) {
+    this.name = name;
+  }
+
+  speak() {
+    console.log(this.name + ' видає звуки.');
+  }
+}
+
+class Lion extends Cat {
+  speak() {
+    super.speak();
+    console.log(this.name + ' ричить.');
+  }
+}
+
+ +

Домішки

+ +

Абстрактні підкласи, або домішки, це шаблони для створення класів. В ECMAScript підклас може мати лише один суперклас, тому множинне наслідування, наприклад, кількох класів інструментів, неможливе. Функціональність має бути надана суперкласом. 

+ +

У ECMAScript для реалізації домішок може використовуватись функція з суперкласом в якості параметра та підкласом, що розширює цей суперклас, в якості значення, що повертається:

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

Клас, що використовує ці домішки, може бути записаний так:

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

Специфікації

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
СпецифікаціяСтатусКоментар
{{SpecName('ES2015', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ES2015')}}Початкове визначення.
{{SpecName('ES2016', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ES2016')}}
{{SpecName('ES2017', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ES2017')}}
{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ESDraft')}}
+ +

Сумісність з веб-переглядачами

+ + + +

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

+ +

Запуск у Чернетці

+ +

Клас не можна перевизначати. Якщо ви працюєте з кодом у Чернетці (меню Firefox Інструменти > Веб-розробка > Чернетка), і 'Запускаєте' визначення класу з тим самим ім'ям двічі, ви отримаєте дивну помилку SyntaxError: redeclaration of let <ім'я-класу>.

+ +

Щоб перезапустити визначення, використовуйте меню Чернетки Виконати > Перезавантажити і запустити.
+ Будь ласка, голосуйте за помилку #1428672.

+ +

Див. також

+ + diff --git a/files/uk/web/javascript/reference/classes/static/index.html b/files/uk/web/javascript/reference/classes/static/index.html new file mode 100644 index 0000000000..3f676d3d6e --- /dev/null +++ b/files/uk/web/javascript/reference/classes/static/index.html @@ -0,0 +1,137 @@ +--- +title: static +slug: Web/JavaScript/Reference/Classes/static +tags: + - ECMAScript 2015 + - JavaScript + - Static + - Класи + - Статичний +translation_of: Web/JavaScript/Reference/Classes/static +--- +
{{jsSidebar("Classes")}}
+ +

Ключове слово static визначає статичний метод класу. Статичні методи не викликаються на екземплярах класу. Вони натомість викликаються на самому класі. Часто це допоміжні функції, такі як функції для створення чи клонування об'єктів.

+ +
{{EmbedInteractiveExample("pages/js/classes-static.html")}}
+ + + +

Синтаксис

+ +
static methodName() { ... }
+ +

Опис

+ +

Виклики статичного методу виконуються безпосередньо через клас, і неможливі на екземплярах класу. Статичні методи часто застосовуються для створення різноманітних допоміжних функцій.

+ +

Виклик статичних методів

+ +

З іншого статичного методу

+ +

Щоб звернутися до статичного методу зсередини іншого статичного методу в межах одного класу, можна використати ключове слово this.

+ +
class StaticMethodCall {
+  static staticMethod() {
+    return 'Викликано статичний метод';
+  }
+  static anotherStaticMethod() {
+    return this.staticMethod() + ' зсередини іншого статичного методу';
+  }
+}
+StaticMethodCall.staticMethod();
+// 'Викликано статичний метод'
+
+StaticMethodCall.anotherStaticMethod();
+// 'Викликано статичний метод зсередини іншого статичного методу'
+ +

Зсередини конструктора класу, чи інших звичайних методів

+ +

Статичні методи недоступні напряму за ключовим словом this зсередини нестатичних методів. Слід викликати їх, використовуючи ім'я класу: CLASSNAME.STATIC_METHOD_NAME(); або ж звертаючись до методу як до властивості конструктора: this.constructor.STATIC_METHOD_NAME().

+ +
class StaticMethodCall {
+  constructor() {
+    console.log(StaticMethodCall.staticMethod());
+    // 'Викликано статичний метод.'
+
+    console.log(this.constructor.staticMethod());
+    // 'Викликано статичний метод.'
+  }
+
+  static staticMethod() {
+    return 'Викликано статичний метод.';
+  }
+}
+ +

Приклади

+ +

Наступний приклад демонструє декілька аспектів:

+ +
    +
  1. Яким чином статичний метод реалізується у класі.
  2. +
  3. Що цей клас із статичним членом може наслідуватись підкласом.
  4. +
  5. Як статичний метод викликати можна, а як — ні.
  6. +
+ +
class Triple {
+  static triple(n) {
+    if (n === undefined) {
+      n = 1;
+    }
+    return n * 3;
+  }
+}
+
+class BiggerTriple extends Triple {
+  static triple(n) {
+    return super.triple(n) * super.triple(n);
+  }
+}
+
+console.log(Triple.triple());        // 3
+console.log(Triple.triple(6));       // 18
+
+var tp = new Triple();
+
+console.log(BiggerTriple.triple(3));
+// 81 (Створення екземпляру предка ніяк не вплинуло на метод нащадка)
+
+console.log(tp.triple());
+// 'tp.triple is not a function'.
+
+ +

Специфікації

+ + + + + + + + + + + + + + + + + + + +
СпецифікаціяСтатусПримітка
{{SpecName('ES2015', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ES2015')}}Первинне визначення.
{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}{{Spec2('ESDraft')}}
+ +

Сумісність з веб-переглядачами

+ + + +

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

+ +

Дивіться також

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