From 8783ae73be8556de82b2532cd719fec76c584313 Mon Sep 17 00:00:00 2001 From: Vitalii_Nesteruk Date: Mon, 1 Nov 2021 19:08:25 +0200 Subject: [PATCH 1/5] Static properties and methods --- .../3-class-extend-object/solution.md | 42 +++---- .../3-class-extend-object/task.md | 16 +-- .../animal-rabbit-static.svg | 2 +- .../03-static-properties-methods/article.md | 112 +++++++++--------- 4 files changed, 86 insertions(+), 86 deletions(-) diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md index ca9e80601..d7e725437 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md @@ -1,14 +1,14 @@ -First, let's see why the latter code doesn't work. +Спочатку подивімося, чому останній код не працює. -The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined". +Причина стає очевидною, якщо ми спробуємо його запустити. Конструктор класу, що успадковується, повинен викликати `super()`. Інакше `"this"` буде не визначене. -So here's the fix: +Виправлення: ```js run class Rabbit extends Object { constructor(name) { *!* - super(); // need to call the parent constructor when inheriting + super(); // потрібно викликати батьківський конструктор під час успадкування */!* this.name = name; } @@ -19,16 +19,16 @@ let rabbit = new Rabbit("Rab"); alert( rabbit.hasOwnProperty('name') ); // true ``` -But that's not all yet. +Але це ще не все. -Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`. +Навіть після виправлення все ще існує важлива різниця між `"class Rabbit extends Object"` та `class Rabbit`. -As we know, the "extends" syntax sets up two prototypes: +Як ми знаємо, синтаксис "extends" встановлює два прототипи: -1. Between `"prototype"` of the constructor functions (for methods). -2. Between the constructor functions themselves (for static methods). +1. Між `"prototype"` функцій-конструкторів (для методів). +2. Між самими функціями-конструкторами (для статичних методів). -In our case, for `class Rabbit extends Object` it means: +У нашому випадку для `class Rabbit extends Object` це означає: ```js run class Rabbit extends Object {} @@ -37,45 +37,45 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) true ``` -So `Rabbit` now provides access to static methods of `Object` via `Rabbit`, like this: +Отже, `Rabbit` тепер надає доступ до статичних методів `Object` через `Rabbit`, наприклад: ```js run class Rabbit extends Object {} *!* -// normally we call Object.getOwnPropertyNames +// зазвичай ми викликаємо Object.getOwnPropertyNames alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b */!* ``` -But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`. +Але якщо у нас немає `extends Object`, тоді для `Rabbit.__proto__` не встановлено значення `Object`. -Here's the demo: +Приклад: ```js run class Rabbit {} alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) false (!) -alert( Rabbit.__proto__ === Function.prototype ); // as any function by default +alert( Rabbit.__proto__ === Function.prototype ); // як у будь-якої функції за замовчуванням *!* -// error, no such function in Rabbit +// помилка, такої функції в Rabbit немає alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error */!* ``` -So `Rabbit` doesn't provide access to static methods of `Object` in that case. +Тому `Rabbit` не надає доступу до статичних методів `Object` у цьому випадку. -By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`. +До речі, `Function.prototype` має "загальні" методи функції, такі як `call`, `bind` тощо. Вони в кінцевому підсумку доступні в обох випадках, тому що для вбудованого конструктора `Object`, `Object.__proto__ = == Функція.прототип`. -Here's the picture: +Приклад на картинці: ![](rabbit-extends-object.svg) -So, to put it short, there are two differences: +Коротко кажучи, є дві відмінності: | class Rabbit | class Rabbit extends Object | |--------------|------------------------------| -| -- | needs to call `super()` in constructor | +| -- | необхідно викликати `super()` в конструкторі | | `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` | diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md index 1d0f98a74..ec2cbc90e 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md @@ -1,12 +1,12 @@ -importance: 3 +важливість: 3 --- -# Class extends Object? +# Клас розширює об'єкт? -As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc. +Як ми знаємо, всі об’єкти зазвичай успадковуються від `Object.prototype` й отримують доступ до «загальних» методів об'єкта, наприклад `hasOwnProperty`. -For instance: +Наприклад: ```js run class Rabbit { @@ -18,16 +18,16 @@ class Rabbit { let rabbit = new Rabbit("Rab"); *!* -// hasOwnProperty method is from Object.prototype +// метод hasOwnProperty від Object.prototype alert( rabbit.hasOwnProperty('name') ); // true */!* ``` -But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`? +Але що як ми пропишемо явно `"class Rabbit extends Object"` - тоді результат буде відрізнятися від звичайного `"class Rabbit"`? -What's the difference? +Яка різниця? -Here's an example of such code (it doesn't work -- why? fix it?): +Ось приклад такого коду (він не працює - чому? виправте його): ```js class Rabbit extends Object { diff --git a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg index 18093d7cf..76e4f4b75 100644 --- a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg +++ b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg @@ -1 +1 @@ -constructor: Animal run: functionAnimal.prototypeconstructor: Rabbit hide: functionRabbit.prototypeAnimalRabbitrabbit[[Prototype]][[Prototype]][[Prototype]]prototypeprototypecomparename: "White Rabbit" \ No newline at end of file +constructor: Animal run: functionAnimal.prototypeconstructor: Rabbit hide: functionRabbit.prototypeAnimalRabbitrabbit[[Prototype]][[Prototype]][[Prototype]]prototypeprototypecomparename: "Білий Кролик" \ No newline at end of file diff --git a/1-js/09-classes/03-static-properties-methods/article.md b/1-js/09-classes/03-static-properties-methods/article.md index c75ec257f..1d9b5dc21 100644 --- a/1-js/09-classes/03-static-properties-methods/article.md +++ b/1-js/09-classes/03-static-properties-methods/article.md @@ -1,9 +1,9 @@ -# Static properties and methods +# Статичні властивості та методи -We can also assign a method to the class function itself, not to its `"prototype"`. Such methods are called *static*. +Ми також можемо присвоїти метод самій функції класу, а не її `"prototype"`. Такі методи називаються *статичними*. -In a class, they are prepended by `static` keyword, like this: +У класі перед ними стоїть ключове слово `static`, наприклад: ```js run class User { @@ -17,7 +17,7 @@ class User { User.staticMethod(); // true ``` -That actually does the same as assigning it as a property directly: +Фактично це те ж саме, що й безпосередньо присвоїти метод як властивість функції: ```js run class User { } @@ -29,11 +29,11 @@ User.staticMethod = function() { User.staticMethod(); // true ``` -The value of `this` in `User.staticMethod()` call is the class constructor `User` itself (the "object before dot" rule). +Значенням `this` при виклику `User.staticMethod()` є сам конструктор класу `User` (правило «об'єкт перед крапкою»). -Usually, static methods are used to implement functions that belong to the class, but not to any particular object of it. +Зазвичай статичні методи використовуються для реалізації функцій, які належать до класу, але не до будь-якого окремого його об’єкта. -For instance, we have `Article` objects and need a function to compare them. A natural solution would be to add `Article.compare` method, like this: +Наприклад, у нас є об’єкти статей `Article` і необхідна функція для їх порівняння. Очевидне рішення - додати метод `Article.compare`, наприклад: ```js run class Article { @@ -49,7 +49,7 @@ class Article { */!* } -// usage +// використання let articles = [ new Article("HTML", new Date(2019, 1, 1)), new Article("CSS", new Date(2019, 0, 1)), @@ -63,17 +63,17 @@ articles.sort(Article.compare); alert( articles[0].title ); // CSS ``` -Here `Article.compare` stands "above" articles, as a means to compare them. It's not a method of an article, but rather of the whole class. +Тут `Article.compare` стоїть «над» статтями, як засіб їх порівняння. Це не метод статті, а скоріше всього класу. -Another example would be a so-called "factory" method. Imagine, we need few ways to create an article: +Іншим прикладом може бути так званий «фабричний» метод. Уявіть собі, нам потрібно кілька способів, щоб створити статтю: -1. Create by given parameters (`title`, `date` etc). -2. Create an empty article with today's date. -3. ...or else somehow. +1. Створити за заданими параметрами (`title`, `date` тощо). +2. Створити порожню статтю з сьогоднішньою датою. +3. ...або якось інакше. -The first way can be implemented by the constructor. And for the second one we can make a static method of the class. +Перший спосіб може бути реалізований через конструктор. А для другого ми можемо використати статичний метод класу. -Like `Article.createTodays()` here: +Такий як `Article.createTodays()` тут: ```js run class Article { @@ -84,56 +84,56 @@ class Article { *!* static createTodays() { - // remember, this = Article - return new this("Today's digest", new Date()); + // пам'ятайте, this = Article + return new this("Сьогоднішній дайджест", new Date()); } */!* } let article = Article.createTodays(); -alert( article.title ); // Today's digest +alert( article.title ); // Сьогоднішній дайджест ``` -Now every time we need to create a today's digest, we can call `Article.createTodays()`. Once again, that's not a method of an article, but a method of the whole class. +Тепер щоразу, коли нам потрібно створити сьогоднішній дайджест, ми можемо викликати `Article.createToday()`. Знову ж таки, це не метод конкретної статті, а метод цілого класу. -Static methods are also used in database-related classes to search/save/remove entries from the database, like this: +Статичні методи також використовуються в класах, що пов’язані з базою даних, для пошуку/збереження/видалення записів із бази даних, наприклад: ```js -// assuming Article is a special class for managing articles -// static method to remove the article: +// припустимо, що Article - це спеціальний клас для керування статтями +// статичний метод видалення статті: Article.remove({id: 12345}); ``` -## Static properties +## Статичні властивості [recent browser=Chrome] -Static properties are also possible, they look like regular class properties, but prepended by `static`: +Статичні властивості також можливі, вони виглядають як звичайні властивості класу, але до них додається `static`: ```js run class Article { - static publisher = "Ilya Kantor"; + static publisher = "Ілля Кантор"; } -alert( Article.publisher ); // Ilya Kantor +alert( Article.publisher ); // Ілля Кантор ``` -That is the same as a direct assignment to `Article`: +Це те саме, що й пряме присвоєння `Article`: ```js -Article.publisher = "Ilya Kantor"; +Article.publisher = "Ілля Кантор"; ``` -## Inheritance of static properties and methods [#statics-and-inheritance] +## Спадкування статичних властивостей і методів [#statics-and-inheritance] -Static properties and methods are inherited. +Статичні властивості та методи наслідуються. -For instance, `Animal.compare` and `Animal.planet` in the code below are inherited and accessible as `Rabbit.compare` and `Rabbit.planet`: +Наприклад, `Animal.compare` та `Animal.planet` у коді нижче успадковуються та доступні як `Rabbit.compare` та `Rabbit.planet`: ```js run class Animal { - static planet = "Earth"; + static planet = "Земля"; constructor(name, speed) { this.speed = speed; @@ -142,7 +142,7 @@ class Animal { run(speed = 0) { this.speed += speed; - alert(`${this.name} runs with speed ${this.speed}.`); + alert(`${this.name} біжить зі швидкістю ${this.speed}.`); } *!* @@ -156,61 +156,61 @@ class Animal { // Inherit from Animal class Rabbit extends Animal { hide() { - alert(`${this.name} hides!`); + alert(`${this.name} ховається!`); } } let rabbits = [ - new Rabbit("White Rabbit", 10), - new Rabbit("Black Rabbit", 5) + new Rabbit("Білий Кролик", 10), + new Rabbit("Чорний Кролик", 5) ]; *!* rabbits.sort(Rabbit.compare); */!* -rabbits[0].run(); // Black Rabbit runs with speed 5. +rabbits[0].run(); // Чорний Кролик біжить зі швидкістю 5. -alert(Rabbit.planet); // Earth +alert(Rabbit.planet); // Земля ``` -Now when we call `Rabbit.compare`, the inherited `Animal.compare` will be called. +Тепер, коли ми викликаємо `Rabbit.compare`, буде викликано успадкований `Animal.compare`. -How does it work? Again, using prototypes. As you might have already guessed, `extends` gives `Rabbit` the `[[Prototype]]` reference to `Animal`. +Як це працює? Знову ж таки, використовуючи прототипи. Як ви вже могли здогадатися, `extends` дає `Rabbit` посилання `[[Prototype]]` на `Animal`. ![](animal-rabbit-static.svg) -So, `Rabbit extends Animal` creates two `[[Prototype]]` references: +Отже, `Rabbit extends Animal` створює два посилання `[[Prototype]]`: -1. `Rabbit` function prototypally inherits from `Animal` function. -2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`. +1. Функція `Rabbit` прототипно успадковує від функції `Animal`. +2. `Rabbit.prototype` прототипно успадковує від `Animal.prototype`. -As a result, inheritance works both for regular and static methods. +В результаті успадкування працює як для звичайних, так і для статичних методів. -Here, let's check that by code: +Перевірмо це кодом: ```js run class Animal {} class Rabbit extends Animal {} -// for statics +// для статичних alert(Rabbit.__proto__ === Animal); // true -// for regular methods +// для звичайних методів alert(Rabbit.prototype.__proto__ === Animal.prototype); // true ``` -## Summary +## Підсумок -Static methods are used for the functionality that belongs to the class "as a whole". It doesn't relate to a concrete class instance. +Статичні методи використовуються для функціональності, що належить до класу «в цілому». Це не стосується конкретного екземпляра класу. -For example, a method for comparison `Article.compare(article1, article2)` or a factory method `Article.createTodays()`. +Наприклад, метод порівняння `Article.compare(article1, article2)` або фабричний метод `Article.createTodays()`. -They are labeled by the word `static` in class declaration. +В оголошенні класу вони позначені ключовим словом `static`. -Static properties are used when we'd like to store class-level data, also not bound to an instance. +Статичні властивості використовуються тоді, коли ми хочемо зберігати дані на рівні класу, а не якогось одного екземпляра. -The syntax is: +Синтаксис: ```js class MyClass { @@ -222,13 +222,13 @@ class MyClass { } ``` -Technically, static declaration is the same as assigning to the class itself: +Технічно, статичне оголошення – це те ж саме, що й присвоєння класу: ```js MyClass.property = ... MyClass.method = ... ``` -Static properties and methods are inherited. +Статичні властивості та методи успадковуються. -For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`. +Для `class B extends A`, прототип класу `B` вказує на `A`: `B.[[Prototype]] = A`. Тож якщо поле не знайдено в `B`, пошук продовжується в `A`. From 3bd239b5f2bf907a0dcd43d3e7e38b33b5e654d2 Mon Sep 17 00:00:00 2001 From: Vitalii_Nesteruk Date: Mon, 1 Nov 2021 19:08:25 +0200 Subject: [PATCH 2/5] Static properties and methods --- .../3-class-extend-object/solution.md | 42 +++---- .../3-class-extend-object/task.md | 14 +-- .../animal-rabbit-static.svg | 2 +- .../03-static-properties-methods/article.md | 112 +++++++++--------- 4 files changed, 85 insertions(+), 85 deletions(-) diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md index ca9e80601..2bdfd261b 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md @@ -1,14 +1,14 @@ -First, let's see why the latter code doesn't work. +Спочатку подивімося, чому останній код не працює. -The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined". +Причина стає очевидною, якщо ми спробуємо його запустити. Конструктор класу, що успадковується, повинен викликати `super()`. Інакше `"this"` буде не визначене. -So here's the fix: +Виправлення: ```js run class Rabbit extends Object { constructor(name) { *!* - super(); // need to call the parent constructor when inheriting + super(); // потрібно викликати батьківський конструктор під час успадкування */!* this.name = name; } @@ -19,16 +19,16 @@ let rabbit = new Rabbit("Rab"); alert( rabbit.hasOwnProperty('name') ); // true ``` -But that's not all yet. +Але це ще не все. -Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`. +Навіть після виправлення все ще існує важлива різниця між `"class Rabbit extends Object"` та `class Rabbit`. -As we know, the "extends" syntax sets up two prototypes: +Як ми знаємо, синтаксис "extends" встановлює два прототипи: -1. Between `"prototype"` of the constructor functions (for methods). -2. Between the constructor functions themselves (for static methods). +1. Між `"prototype"` функцій-конструкторів (для методів). +2. Між самими функціями-конструкторами (для статичних методів). -In our case, for `class Rabbit extends Object` it means: +У нашому випадку для `class Rabbit extends Object` це означає: ```js run class Rabbit extends Object {} @@ -37,45 +37,45 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) true ``` -So `Rabbit` now provides access to static methods of `Object` via `Rabbit`, like this: +Отже, `Rabbit` тепер надає доступ до статичних методів `Object` через `Rabbit`, наприклад: ```js run class Rabbit extends Object {} *!* -// normally we call Object.getOwnPropertyNames +// зазвичай ми викликаємо Object.getOwnPropertyNames alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b */!* ``` -But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`. +Але якщо у нас немає `extends Object`, тоді для `Rabbit.__proto__` не встановлено значення `Object`. -Here's the demo: +Приклад: ```js run class Rabbit {} alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) false (!) -alert( Rabbit.__proto__ === Function.prototype ); // as any function by default +alert( Rabbit.__proto__ === Function.prototype ); // як у будь-якої функції за замовчуванням *!* -// error, no such function in Rabbit +// помилка, такої функції в Rabbit немає alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error */!* ``` -So `Rabbit` doesn't provide access to static methods of `Object` in that case. +Тому `Rabbit` не надає доступу до статичних методів `Object` у цьому випадку. -By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`. +До речі, `Function.prototype` має "загальні" методи функції, такі як `call`, `bind` тощо. Вони в кінцевому підсумку доступні в обох випадках, тому що для вбудованого конструктора `Object`, `Object.__proto__ === Function.prototype`. -Here's the picture: +Приклад на картинці: ![](rabbit-extends-object.svg) -So, to put it short, there are two differences: +Коротко кажучи, є дві відмінності: | class Rabbit | class Rabbit extends Object | |--------------|------------------------------| -| -- | needs to call `super()` in constructor | +| -- | необхідно викликати `super()` в конструкторі | | `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` | diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md index 1d0f98a74..e777f7dde 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md @@ -2,11 +2,11 @@ importance: 3 --- -# Class extends Object? +# Клас розширює об’єкт? -As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc. +Як ми знаємо, всі об’єкти зазвичай успадковуються від `Object.prototype` й отримують доступ до «загальних» методів об’єкта, наприклад `hasOwnProperty` тощо. -For instance: +Наприклад: ```js run class Rabbit { @@ -18,16 +18,16 @@ class Rabbit { let rabbit = new Rabbit("Rab"); *!* -// hasOwnProperty method is from Object.prototype +// метод hasOwnProperty від Object.prototype alert( rabbit.hasOwnProperty('name') ); // true */!* ``` -But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`? +Але що як ми пропишемо явно `"class Rabbit extends Object"` - тоді результат буде відрізнятися від звичайного `"class Rabbit"`? -What's the difference? +Яка різниця? -Here's an example of such code (it doesn't work -- why? fix it?): +Ось приклад такого коду (він не працює - чому? виправте його): ```js class Rabbit extends Object { diff --git a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg index 18093d7cf..76e4f4b75 100644 --- a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg +++ b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg @@ -1 +1 @@ -constructor: Animal run: functionAnimal.prototypeconstructor: Rabbit hide: functionRabbit.prototypeAnimalRabbitrabbit[[Prototype]][[Prototype]][[Prototype]]prototypeprototypecomparename: "White Rabbit" \ No newline at end of file +constructor: Animal run: functionAnimal.prototypeconstructor: Rabbit hide: functionRabbit.prototypeAnimalRabbitrabbit[[Prototype]][[Prototype]][[Prototype]]prototypeprototypecomparename: "Білий Кролик" \ No newline at end of file diff --git a/1-js/09-classes/03-static-properties-methods/article.md b/1-js/09-classes/03-static-properties-methods/article.md index c75ec257f..8f0620ca7 100644 --- a/1-js/09-classes/03-static-properties-methods/article.md +++ b/1-js/09-classes/03-static-properties-methods/article.md @@ -1,9 +1,9 @@ -# Static properties and methods +# Статичні властивості та методи -We can also assign a method to the class function itself, not to its `"prototype"`. Such methods are called *static*. +Ми також можемо присвоїти метод самій функції класу, а не її `"prototype"`. Такі методи називаються *статичними*. -In a class, they are prepended by `static` keyword, like this: +У класі перед ними стоїть ключове слово `static`, наприклад: ```js run class User { @@ -17,7 +17,7 @@ class User { User.staticMethod(); // true ``` -That actually does the same as assigning it as a property directly: +Фактично це те ж саме, що й безпосередньо присвоїти метод як властивість функції: ```js run class User { } @@ -29,11 +29,11 @@ User.staticMethod = function() { User.staticMethod(); // true ``` -The value of `this` in `User.staticMethod()` call is the class constructor `User` itself (the "object before dot" rule). +Значенням `this` при виклику `User.staticMethod()` є сам конструктор класу `User` (правило «об’єкт перед крапкою»). -Usually, static methods are used to implement functions that belong to the class, but not to any particular object of it. +Зазвичай статичні методи використовуються для реалізації функцій, які належать до класу, але не до будь-якого окремого його об’єкта. -For instance, we have `Article` objects and need a function to compare them. A natural solution would be to add `Article.compare` method, like this: +Наприклад, у нас є об’єкти статей `Article` і необхідна функція для їх порівняння. Очевидне рішення - додати метод `Article.compare`, наприклад: ```js run class Article { @@ -49,7 +49,7 @@ class Article { */!* } -// usage +// використання let articles = [ new Article("HTML", new Date(2019, 1, 1)), new Article("CSS", new Date(2019, 0, 1)), @@ -63,17 +63,17 @@ articles.sort(Article.compare); alert( articles[0].title ); // CSS ``` -Here `Article.compare` stands "above" articles, as a means to compare them. It's not a method of an article, but rather of the whole class. +Тут `Article.compare` стоїть «над» статтями, як засіб їх порівняння. Це не метод статті, а скоріше всього класу. -Another example would be a so-called "factory" method. Imagine, we need few ways to create an article: +Іншим прикладом може бути так званий «фабричний» метод. Уявіть собі, нам потрібно кілька способів, щоб створити статтю: -1. Create by given parameters (`title`, `date` etc). -2. Create an empty article with today's date. -3. ...or else somehow. +1. Створити за заданими параметрами (`title`, `date` тощо). +2. Створити порожню статтю з сьогоднішньою датою. +3. ...або якось інакше. -The first way can be implemented by the constructor. And for the second one we can make a static method of the class. +Перший спосіб може бути реалізований через конструктор. А для другого ми можемо використати статичний метод класу. -Like `Article.createTodays()` here: +Такий як `Article.createTodays()` тут: ```js run class Article { @@ -84,56 +84,56 @@ class Article { *!* static createTodays() { - // remember, this = Article - return new this("Today's digest", new Date()); + // пам’ятайте, this = Article + return new this("Сьогоднішній дайджест", new Date()); } */!* } let article = Article.createTodays(); -alert( article.title ); // Today's digest +alert( article.title ); // Сьогоднішній дайджест ``` -Now every time we need to create a today's digest, we can call `Article.createTodays()`. Once again, that's not a method of an article, but a method of the whole class. +Тепер щоразу, коли нам потрібно створити сьогоднішній дайджест, ми можемо викликати `Article.createToday()`. Знову ж таки, це не метод конкретної статті, а метод цілого класу. -Static methods are also used in database-related classes to search/save/remove entries from the database, like this: +Статичні методи також використовуються в класах, що пов’язані з базою даних, для пошуку/збереження/видалення записів із бази даних, наприклад: ```js -// assuming Article is a special class for managing articles -// static method to remove the article: +// припустимо, що Article - це спеціальний клас для керування статтями +// статичний метод видалення статті: Article.remove({id: 12345}); ``` -## Static properties +## Статичні властивості [recent browser=Chrome] -Static properties are also possible, they look like regular class properties, but prepended by `static`: +Статичні властивості також можливі, вони виглядають як звичайні властивості класу, але до них додається `static`: ```js run class Article { - static publisher = "Ilya Kantor"; + static publisher = "Ілля Кантор"; } -alert( Article.publisher ); // Ilya Kantor +alert( Article.publisher ); // Ілля Кантор ``` -That is the same as a direct assignment to `Article`: +Це те саме, що й пряме присвоєння `Article`: ```js -Article.publisher = "Ilya Kantor"; +Article.publisher = "Ілля Кантор"; ``` -## Inheritance of static properties and methods [#statics-and-inheritance] +## Спадкування статичних властивостей і методів [#statics-and-inheritance] -Static properties and methods are inherited. +Статичні властивості та методи наслідуються. -For instance, `Animal.compare` and `Animal.planet` in the code below are inherited and accessible as `Rabbit.compare` and `Rabbit.planet`: +Наприклад, `Animal.compare` та `Animal.planet` у коді нижче успадковуються та доступні як `Rabbit.compare` та `Rabbit.planet`: ```js run class Animal { - static planet = "Earth"; + static planet = "Земля"; constructor(name, speed) { this.speed = speed; @@ -142,7 +142,7 @@ class Animal { run(speed = 0) { this.speed += speed; - alert(`${this.name} runs with speed ${this.speed}.`); + alert(`${this.name} біжить зі швидкістю ${this.speed}.`); } *!* @@ -156,61 +156,61 @@ class Animal { // Inherit from Animal class Rabbit extends Animal { hide() { - alert(`${this.name} hides!`); + alert(`${this.name} ховається!`); } } let rabbits = [ - new Rabbit("White Rabbit", 10), - new Rabbit("Black Rabbit", 5) + new Rabbit("Білий Кролик", 10), + new Rabbit("Чорний Кролик", 5) ]; *!* rabbits.sort(Rabbit.compare); */!* -rabbits[0].run(); // Black Rabbit runs with speed 5. +rabbits[0].run(); // Чорний Кролик біжить зі швидкістю 5. -alert(Rabbit.planet); // Earth +alert(Rabbit.planet); // Земля ``` -Now when we call `Rabbit.compare`, the inherited `Animal.compare` will be called. +Тепер, коли ми викликаємо `Rabbit.compare`, буде викликано успадкований `Animal.compare`. -How does it work? Again, using prototypes. As you might have already guessed, `extends` gives `Rabbit` the `[[Prototype]]` reference to `Animal`. +Як це працює? Знову ж таки, використовуючи прототипи. Як ви вже могли здогадатися, `extends` дає `Rabbit` посилання `[[Prototype]]` на `Animal`. ![](animal-rabbit-static.svg) -So, `Rabbit extends Animal` creates two `[[Prototype]]` references: +Отже, `Rabbit extends Animal` створює два посилання `[[Prototype]]`: -1. `Rabbit` function prototypally inherits from `Animal` function. -2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`. +1. Функція `Rabbit` прототипно успадковує від функції `Animal`. +2. `Rabbit.prototype` прототипно успадковує від `Animal.prototype`. -As a result, inheritance works both for regular and static methods. +В результаті успадкування працює як для звичайних, так і для статичних методів. -Here, let's check that by code: +Перевірмо це кодом: ```js run class Animal {} class Rabbit extends Animal {} -// for statics +// для статичних alert(Rabbit.__proto__ === Animal); // true -// for regular methods +// для звичайних методів alert(Rabbit.prototype.__proto__ === Animal.prototype); // true ``` -## Summary +## Підсумки -Static methods are used for the functionality that belongs to the class "as a whole". It doesn't relate to a concrete class instance. +Статичні методи використовуються для функціональності, що належить до класу «в цілому». Це не стосується конкретного екземпляра класу. -For example, a method for comparison `Article.compare(article1, article2)` or a factory method `Article.createTodays()`. +Наприклад, метод порівняння `Article.compare(article1, article2)` або фабричний метод `Article.createTodays()`. -They are labeled by the word `static` in class declaration. +В оголошенні класу вони позначені ключовим словом `static`. -Static properties are used when we'd like to store class-level data, also not bound to an instance. +Статичні властивості використовуються тоді, коли ми хочемо зберігати дані на рівні класу, а не якогось одного екземпляра. -The syntax is: +Синтаксис: ```js class MyClass { @@ -222,13 +222,13 @@ class MyClass { } ``` -Technically, static declaration is the same as assigning to the class itself: +Технічно, статичне оголошення – це те ж саме, що й присвоєння класу: ```js MyClass.property = ... MyClass.method = ... ``` -Static properties and methods are inherited. +Статичні властивості та методи успадковуються. -For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`. +Для `class B extends A`, прототип класу `B` вказує на `A`: `B.[[Prototype]] = A`. Тож якщо поле не знайдено в `B`, пошук продовжується в `A`. From f661d519e3ae3c61f645c5405d86c53e442f41cc Mon Sep 17 00:00:00 2001 From: Vitalii_Nesteruk Date: Tue, 2 Nov 2021 11:28:33 +0200 Subject: [PATCH 3/5] Extending built-in classes --- 1-js/09-classes/05-extend-natives/article.md | 48 ++++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/1-js/09-classes/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md index 28b4c6eb6..a46b34a28 100644 --- a/1-js/09-classes/05-extend-natives/article.md +++ b/1-js/09-classes/05-extend-natives/article.md @@ -1,12 +1,12 @@ -# Extending built-in classes +# Розширення вбудованих класів -Built-in classes like Array, Map and others are extendable also. +Вбудовані класи, такі як Array, Map та інші, також розширюються. -For instance, here `PowerArray` inherits from the native `Array`: +Наприклад, ось тут `PowerArray` успадковується від вбудованого `Array`: ```js run -// add one more method to it (can do more) +// додамо до нього ще один метод (можна більше) class PowerArray extends Array { isEmpty() { return this.length === 0; @@ -21,20 +21,20 @@ alert(filteredArr); // 10, 50 alert(filteredArr.isEmpty()); // false ``` -Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type `PowerArray`. Their internal implementation uses the object's `constructor` property for that. +Зверніть увагу на дуже цікаву річ. Вбудовані методи, такі як `filter`, `map` та інші, повертають нові об’єкти точно успадкованого типу `PowerArray`. Їхня внутрішня реалізація використовує для цього властивість об’єкта `constructor`. -In the example above, +У вищенаведеному прикладі, ```js arr.constructor === PowerArray ``` -When `arr.filter()` is called, it internally creates the new array of results using exactly `arr.constructor`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result. +Коли викликається `arr.filter()`, він внутрішньо створює новий масив результатів, використовуючи саме `arr.constructor`, а не базовий `Array`. Насправді це дуже круто, тому що ми можемо продовжувати використовувати методи `PowerArray` і далі для отримання результату. -Even more, we can customize that behavior. +Щобільше, ми можемо налаштувати таку поведінку. -We can add a special static getter `Symbol.species` to the class. If it exists, it should return the constructor that JavaScript will use internally to create new entities in `map`, `filter` and so on. +Ми можемо додати до класу спеціальний статичний геттер `Symbol.species`. Якщо він існує, то повинен повернути конструктор, який JavaScript буде використовувати внутрішньо для створення нових об’єктів у `map`, `filter` тощо. -If we'd like built-in methods like `map` or `filter` to return regular arrays, we can return `Array` in `Symbol.species`, like here: +Якщо ж ми хочемо, щоб вбудовані методи, такі як `map` або `filter`, повертали звичайні масиви, ми можемо повернути `Array` у `Symbol.species`, як тут: ```js run class PowerArray extends Array { @@ -43,7 +43,7 @@ class PowerArray extends Array { } *!* - // built-in methods will use this as the constructor + // вбудовані методи використовуватимуть це як конструктор static get [Symbol.species]() { return Array; } @@ -53,37 +53,37 @@ class PowerArray extends Array { let arr = new PowerArray(1, 2, 5, 10, 50); alert(arr.isEmpty()); // false -// filter creates new array using arr.constructor[Symbol.species] as constructor +// filter створює новий масив, використовуючи arr.constructor[Symbol.species] як конструктор let filteredArr = arr.filter(item => item >= 10); *!* -// filteredArr is not PowerArray, but Array +// filteredArr - це не PowerArray, а Array */!* alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function ``` -As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further. +Як бачите, тепер `.filter` повертає `Array`. Таким чином, розширена функціональність не передається далі. ```smart header="Other collections work similarly" -Other collections, such as `Map` and `Set`, work alike. They also use `Symbol.species`. +Інші колекції, такі як `Map` і `Set`, працюють однаково. Вони також використовують `Symbol.species`. ``` -## No static inheritance in built-ins +## Відсутність статичного спадкування вбудованих класів -Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc. +Вбудовані об’єкти мають власні статичні методи, наприклад `Object.keys`, `Array.isArray` тощо. -As we already know, native classes extend each other. For instance, `Array` extends `Object`. +Як ми вже знаємо, вбудовані класи розширюють один одного. Наприклад, `Array` розширює `Object`. -Normally, when one class extends another, both static and non-static methods are inherited. That was thoroughly explained in the article [](info:static-properties-methods#statics-and-inheritance). +Зазвичай, коли один клас розширює інший, успадковуються як статичні, так і нестатичні методи. Це детально описано в статті [](info:static-properties-methods#static-and-inheritance). -But built-in classes are an exception. They don't inherit statics from each other. +Але вбудовані класи є винятком. Вони не успадковують статику один від одного. -For example, both `Array` and `Date` inherit from `Object`, so their instances have methods from `Object.prototype`. But `Array.[[Prototype]]` does not reference `Object`, so there's no, for instance, `Array.keys()` (or `Date.keys()`) static method. +Наприклад, і `Array`, і `Date` успадковуються від `Object`, тому їхні екземпляри мають методи з `Object.prototype`. Але `Array.[[Prototype]]` не посилається на `Object`, тому не існує, наприклад, `Array.keys()` (або `Date.keys()`) статичного методу. -Here's the picture structure for `Date` and `Object`: +Ось структура зображення для `Date` та `Object`: ![](object-date-inheritance.svg) -As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`. +Як бачите, немає зв’язку між `Date` і `Object`. Вони незалежні, лише `Date.prototype` успадковується від `Object.prototype`. -That's an important difference of inheritance between built-in objects compared to what we get with `extends`. +Це важлива відмінність успадкування між вбудованими об’єктами в порівнянні з тим, що ми отримуємо за допомогою `extends`. From 43bd61a24b07f5a77e1bf32aa07f094e77bbdd6a Mon Sep 17 00:00:00 2001 From: Taras Date: Tue, 2 Nov 2021 14:29:04 +0200 Subject: [PATCH 4/5] Update 1-js/09-classes/05-extend-natives/article.md --- 1-js/09-classes/05-extend-natives/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/09-classes/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md index a46b34a28..ed56d629d 100644 --- a/1-js/09-classes/05-extend-natives/article.md +++ b/1-js/09-classes/05-extend-natives/article.md @@ -64,7 +64,7 @@ alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function Як бачите, тепер `.filter` повертає `Array`. Таким чином, розширена функціональність не передається далі. -```smart header="Other collections work similarly" +```smart header="Інші колекції працюють аналогічно" Інші колекції, такі як `Map` і `Set`, працюють однаково. Вони також використовують `Symbol.species`. ``` From db0ac39b891f0bc6a16fda96f24597c923bbd038 Mon Sep 17 00:00:00 2001 From: Taras Date: Tue, 2 Nov 2021 14:29:13 +0200 Subject: [PATCH 5/5] Update 1-js/09-classes/05-extend-natives/article.md --- 1-js/09-classes/05-extend-natives/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/09-classes/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md index ed56d629d..4c86f5c6c 100644 --- a/1-js/09-classes/05-extend-natives/article.md +++ b/1-js/09-classes/05-extend-natives/article.md @@ -65,7 +65,7 @@ alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function Як бачите, тепер `.filter` повертає `Array`. Таким чином, розширена функціональність не передається далі. ```smart header="Інші колекції працюють аналогічно" -Інші колекції, такі як `Map` і `Set`, працюють однаково. Вони також використовують `Symbol.species`. +Інші колекції, такі як `Map` і `Set`, працюють аналогічно. Вони також використовують `Symbol.species`. ``` ## Відсутність статичного спадкування вбудованих класів