From 4c9ecb9561f54915e5c4c40df792a83bb5c3b058 Mon Sep 17 00:00:00 2001 From: Volodymyr Sych Date: Thu, 29 Jul 2021 19:24:28 +0300 Subject: [PATCH 01/24] Prototypal inheritance --- .../01-prototype-inheritance/article.md | 173 +++++++++--------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 02236af75..8f5a15dea 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -1,22 +1,22 @@ -# Prototypal inheritance +# Успадкування через прототипи -In programming, we often want to take something and extend it. +У програмуванні ми часто хочемо щось взяти і доповнити чи розширити. -For instance, we have a `user` object with its properties and methods, and want to make `admin` and `guest` as slightly modified variants of it. We'd like to reuse what we have in `user`, not copy/reimplement its methods, just build a new object on top of it. +Наприклад, ми маємо об’єкт 'user' з його властивостями та методами, і хочемо створити 'admin' та 'guest' як дещо змінені варіанти об’єкта 'user'. Тобто ми хочемо повторно використовувати те, що ми маємо в 'user', але також додати ще власні методи і властивості. Іншими словами, просто хочемо збудувати новий об’єкт поверх того, що існує. -*Prototypal inheritance* is a language feature that helps in that. +*успадкування через прототипи* - це те, що нам допоможе в цьому. -## [[Prototype]] +## Спеціальна властивість '[[Prototype]]' -In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype": +В JavaScript, об’єкти мають спеціальну приховану властивість '[[Prototype]]' (як зазначено в специфікаціях мови), яка може приймати значення: або 'null', або мати посилання на інший об’єкт. Цей об’єкт називається 'прототип': ![prototype](object-prototype-empty.svg) -When we read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, this is called "prototypal inheritance". And soon we'll study many examples of such inheritance, as well as cooler language features built upon it. +Коли ми зчитуємо якусь властивість об’єкта 'object', але її не має, JavaScript автоматично бере її з прототипу. В програмуванні це називається 'успадкування через прототипи'. В скорому часі, ми вивчимо багато прикладів такого успадкування, як і створення більш цікавих прикладів, які побудовані на їх основі. -The property `[[Prototype]]` is internal and hidden, but there are many ways to set it. +Така властивість '[[Prototype]]' є внутрішньою та прихованою, але є багато шляхів щоб її визначити. -One of them is to use the special name `__proto__`, like this: +Одним з них є використання спеціального імені '__proto__', наприклад: ```js run let animal = { @@ -27,13 +27,13 @@ let rabbit = { }; *!* -rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal +rabbit.__proto__ = animal; // тут встановлюємо rabbit.[[Prototype]] = animal */!* ``` -Now if we read a property from `rabbit`, and it's missing, JavaScript will automatically take it from `animal`. +І тепер, якщо ми зчитуємо властивість з об’єкта 'rabbit', а її немає то JavaScript автоматично візьме її з 'animal'. -For instance: +Ось ще приклад: ```js let animal = { @@ -47,24 +47,24 @@ let rabbit = { rabbit.__proto__ = animal; // (*) */!* -// we can find both properties in rabbit now: +// тепер ми можемо знайти обидві властивості в об’єкті 'rabbit': *!* alert( rabbit.eats ); // true (**) */!* alert( rabbit.jumps ); // true ``` -Here the line `(*)` sets `animal` to be a prototype of `rabbit`. +В позначеному рядку (*), об’єкт 'animal' визначається як прототип для об’єкта 'rabbit'. -Then, when `alert` tries to read property `rabbit.eats` `(**)`, it's not in `rabbit`, so JavaScript follows the `[[Prototype]]` reference and finds it in `animal` (look from the bottom up): +І коли 'alert' намагається прочитати властивість 'rabbit.eats' на рядку позначеному (**), а її там немає, то JavaScript йде по ссилці '[[Prototype]]' та знаходить її в об’єкті 'animal' (дивіться знизу вверх): ![](proto-animal-rabbit.svg) -Here we can say that "`animal` is the prototype of `rabbit`" or "`rabbit` prototypically inherits from `animal`". +Ми можемо сказати, що 'animal' є прототипом для 'rabbit', або так - об’єкт 'rabbit' успадковує властивості об’єкта 'animal'. -So if `animal` has a lot of useful properties and methods, then they become automatically available in `rabbit`. Such properties are called "inherited". +Якщо 'animal' має багато корисних властивостей та методів, вони стають автоматично доступними для 'rabbit'. Такі властивості називаються 'успадкованими'. -If we have a method in `animal`, it can be called on `rabbit`: +Також, якщо ми маємо методи в 'animal' то вони можуть бути викликані і в 'rabbit': ```js run let animal = { @@ -81,17 +81,17 @@ let rabbit = { __proto__: animal }; -// walk is taken from the prototype +// тут метод 'walk' береться з прототипу *!* -rabbit.walk(); // Animal walk +rabbit.walk(); // отримуємо 'Animal walk' */!* ``` -The method is automatically taken from the prototype, like this: +Методи автоматично беруться з прототипу, як тут: ![](proto-animal-rabbit-walk.svg) -The prototype chain can be longer: +Ланцюг прототипів може бути навіть довшим: ```js run let animal = { @@ -115,48 +115,47 @@ let longEar = { */!* }; -// walk is taken from the prototype chain -longEar.walk(); // Animal walk -alert(longEar.jumps); // true (from rabbit) +// Метод 'walk' беремо з ланцюжка прототипів +longEar.walk(); // отримуємо 'Animal walk' +alert(longEar.jumps); // true (береться з об’єкта 'rabbit') ``` ![](proto-animal-rabbit-chain.svg) -Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`. +І тепер, якщо ми хочемо взяти метод з об’єкта 'longEar', а його там не має, JavaScript буде шукати його в 'rabbit', далі в 'animal'. -There are only two limitations: +Існує два обмеження: -1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle. -2. The value of `__proto__` can be either an object or `null`. Other types are ignored. +1. Посилання через прототипи не може бути замкнено в кільце. JavaScript видасть помилку, якщо ми визначемо '__proto__' в ланцюжку прототипів і замкнем його в кільце. +2. Значення '__proto__' може бути, або посиланням на об'єк, або 'null'. Інші типи значень - ігноруються. -Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others. +Хоч це і очевидно, але все ж таки: може бути тільки одина властивість '[[Prototype]]'. Об’єкт не може успадковувати властивості та методи від двох прототипів одночасно. -```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" -It's a common mistake of novice developers not to know the difference between these two. +```smart header="'__proto__' є старим і давнім getter/setter для '[[Prototype]]'" +Вважається поширеною помилкою, особливо для початківців, неможливість чітко визначити різницю між двома поняттями '__proto__' та '[[Prototype]]'. -Please note that `__proto__` is *not the same* as the internal `[[Prototype]]` property. It's a getter/setter for `[[Prototype]]`. Later we'll see situations where it matters, for now let's just keep it in mind, as we build our understanding of JavaScript language. +Будь ласка зауважте, що властивість '__proto__' *не є тою самою* властивістю як внутрішня властивість '[[Prototype]]'. Це є 'getter/setter' для '[[Prototype]]'. Пізніше ми побачимо ситуації, коли це важливо, а поки що давайте просто мати це на увазі, примножуючи своє розуміння мови JavaScript. +Властивість '__proto__' вважається трохи застарілим. Вона існує з історичних причин, сучасна мова JavaScript пропонує використовувати функцію 'Object.getPrototypeOf/Object.setPrototypeOf' замість 'get/set' прототипу. Ми також розберем ці функції пізніше. -The `__proto__` property is a bit outdated. It exists for historical reasons, modern JavaScript suggests that we should use `Object.getPrototypeOf/Object.setPrototypeOf` functions instead that get/set the prototype. We'll also cover these functions later. +Згідно специфікаціям мови, '__proto__' повинно тільки підтримуватись в браузерах. Проте насправді, усі середовища, включаючи серверні, підтримують '__proto__', а тому використовувати його можна досить безпечно. -By the specification, `__proto__` must only be supported by browsers. In fact though, all environments including server-side support `__proto__`, so we're quite safe using it. - -As the `__proto__` notation is a bit more intuitively obvious, we use it in the examples. +Оскільки позначення '__proto__' більш інтуїтивно зрозуміліше, ми будемо його використовуємо в прикладах. ``` -## Writing doesn't use prototype +## Операція по запису/видаленню не застосовується на прототипах -The prototype is only used for reading properties. +Прототипи можна використовувати тільки для зчитування властивостей. -Write/delete operations work directly with the object. +А такі операції як запис/видалення, працюють напряму тільки на самому об’єкті. -In the example below, we assign its own `walk` method to `rabbit`: +У прикладі нижче, ми визначаємо власний метод 'walk' для об’єкта 'rabbit': ```js run let animal = { eats: true, walk() { - /* this method won't be used by rabbit */ + /* цей метод не буде використаний об’єктом 'rabbit' */ } }; @@ -170,16 +169,16 @@ rabbit.walk = function() { }; */!* -rabbit.walk(); // Rabbit! Bounce-bounce! +rabbit.walk(); // тут отримаємо 'Rabbit! Bounce-bounce!' ``` -From now on, `rabbit.walk()` call finds the method immediately in the object and executes it, without using the prototype: +Як тільки ми задаємо метод таким чином 'rabbit.walk()', виклик одразу знайде його на самому об’єкті та виконає без використання такого самого методу, який визначений в прототипі: ![](proto-animal-rabbit-walk-2.svg) -Accessor properties are an exception, as assignment is handled by a setter function. So writing to such a property is actually the same as calling a function. +Властивості 'Accessor' є винятком, оскільки присвоєння обробляється функцією встановлення (через 'setter'). Отже, запис у таку властивість насправді те саме, що виклик функції. -For that reason `admin.fullName` works correctly in the code below: +З цієї причини 'admin.fullName' коректно працює в коді, що показаний нижче: ```js run let user = { @@ -202,33 +201,33 @@ let admin = { alert(admin.fullName); // John Smith (*) -// setter triggers! +// відпрацьовує setter admin.fullName = "Alice Cooper"; // (**) -alert(admin.fullName); // Alice Cooper, state of admin modified -alert(user.fullName); // John Smith, state of user protected +alert(admin.fullName); // Alice Cooper, стан об’єкта 'admin' було змінено +alert(user.fullName); // John Smith, стан об’єкта 'user' захищено ``` -Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called. +Тут на рядку позначеному (*), властивість 'admin.fullName' викликається через 'getter' визначений в прототипі 'user'. А на рядку позначеному (**) властивість задається через setter, який також визначений в прототипі. -## The value of "this" +## Значення ключового слова "this" -An interesting question may arise in the example above: what's the value of `this` inside `set fullName(value)`? Where are the properties `this.name` and `this.surname` written: into `user` or `admin`? +Цікаве питання може виникнути в прикладі вище: яке значення ключового слова 'this' всередині 'set fullName(value)'? Де визначаютья властивості 'this.name' та 'this.surname': в об’єкті 'user' чи 'admin'? -The answer is simple: `this` is not affected by prototypes at all. +Відповідь проста: на 'this' не впливає прототип узагалі. -**No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot.** +**Незалежно від того, де метод визначений: в об’єкті чи його прототипі, ключове слово 'this' завжди вказує на об’єкт перед крапкою.** -So, the setter call `admin.fullName=` uses `admin` as `this`, not `user`. +Таким чином, виклик в методі 'set' виразу 'admin.fullName=' буде брати як 'this' значення властивостей з об’єкту 'admin' а не 'user'. -That is actually a super-important thing, because we may have a big object with many methods, and have objects that inherit from it. And when the inheriting objects run the inherited methods, they will modify only their own states, not the state of the big object. +В дійсності це є дуже важлива річ бо наприклад, ми можемо мати дуже великий об’єкт з багатьма методами, і також маємо об’єкти, які успадковують властивості або методи від того великого об’єкту. Коли успадковані методи викликаються на стороні об’єктів, що їх успадкували, вони можуть змінювати тільки свої стани а не стан того великого об’єкту. -For instance, here `animal` represents a "method storage", and `rabbit` makes use of it. +У цьому прикладі, об’єкт 'animal' представляє "набір методів", а об’єкт 'rabbit' може використовувати якісь з цих методів. -The call `rabbit.sleep()` sets `this.isSleeping` on the `rabbit` object: +Виклик 'rabbit.sleep()' встановлює 'this.isSleeping' в об’єкті 'rabbit': ```js run -// animal has methods +// об’єкт 'animal' має набір методів has let animal = { walk() { if (!this.isSleeping) { @@ -245,26 +244,26 @@ let rabbit = { __proto__: animal }; -// modifies rabbit.isSleeping +// змінює тільки свій стан методом rabbit.isSleeping rabbit.sleep(); alert(rabbit.isSleeping); // true -alert(animal.isSleeping); // undefined (no such property in the prototype) +alert(animal.isSleeping); // undefined (немає такого методу в прототипі) ``` -The resulting picture: +Остаточний вигляд: ![](proto-animal-rabbit-walk-3.svg) -If we had other objects, like `bird`, `snake`, etc., inheriting from `animal`, they would also gain access to methods of `animal`. But `this` in each method call would be the corresponding object, evaluated at the call-time (before dot), not `animal`. So when we write data into `this`, it is stored into these objects. +Якщо ми маємо інші об’єкти: 'bird', 'snake', і т.д, які успадковують методи від об’єкта 'animal'. Кожний раз, при виклику будь-якого методу, ключове слово 'this' буде вказувати на той об’єкт, на стороні якого був викликаний цей метод, а не на об’єкт 'animal'. Отже, коли ми записуємо будь-які дані в 'this', вони зберігаються в об’єктах на які і вказує 'this'. -As a result, methods are shared, but the object state is not. +Як результат, методи можуть успадковуватись (передаватись), але стани об’єктів - не можуть. -## for..in loop +## цикл for..in -The `for..in` loop iterates over inherited properties too. +Цикл 'for..in' може проходитись по успадкованим властивостям також. -For instance: +Наприклад: ```js run let animal = { @@ -277,19 +276,19 @@ let rabbit = { }; *!* -// Object.keys only returns own keys +// Object.keys повертає тільки влвасні ключі alert(Object.keys(rabbit)); // jumps */!* *!* -// for..in loops over both own and inherited keys -for(let prop in rabbit) alert(prop); // jumps, then eats +// Цикл for..in loops повертає як власні так і успадковані ключі +for(let prop in rabbit) alert(prop); // jumps, потім eats */!* ``` -If that's not what we want, and we'd like to exclude inherited properties, there's a built-in method [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`. +Якщо це не те, що нам потрібно, і ми б хотіли виключити отримання успадкованих значень, існує вбудований метод '[obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty)', який повертає 'true' якщо 'obj' має тільки власні (не успадковані) властивості. -So we can filter out inherited properties (or do something else with them): +Отже, ми можемо відфільтрувати успадковані властивості (чи щось зробити з ними інше ): ```js run let animal = { @@ -312,28 +311,28 @@ for(let prop in rabbit) { } ``` -Here we have the following inheritance chain: `rabbit` inherits from `animal`, that inherits from `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it: +У цьому прикладі ми маємо наступний ланцюжок: 'rabbit' успадковує властивості від об’єкта 'animal', який, у свою чергу, успадковує властивості від глобального 'Object.prototype' (тому що 'animal' є літералом об’єкта '{...}' за замовчуванням) і на самому верху маємо 'null': ![](rabbit-animal-object.svg) -Note, there's one funny thing. Where is the method `rabbit.hasOwnProperty` coming from? We did not define it. Looking at the chain we can see that the method is provided by `Object.prototype.hasOwnProperty`. In other words, it's inherited. +Зауважте одну цікаву річ: звідки метод 'rabbit.hasOwnProperty' забезпечує роботу свого функціоналу, адже властивості на той момент ще не визначені. Дивлячись на ланцюжок успадкувань ми можемо побачити, що отримання властивостей забезпечується 'Object.prototype.hasOwnProperty'. Іншими словами, властивості успадковуються. -...But why does `hasOwnProperty` not appear in the `for..in` loop like `eats` and `jumps` do, if `for..in` lists inherited properties? +...але чому метод 'hasOwnProperty' не визначає в циклі 'for..in' властивості 'eats' та 'jumps', якщо сам цикл 'for..in' ітерує або проходить по цим успадкованим властивостям? -The answer is simple: it's not enumerable. Just like all other properties of `Object.prototype`, it has `enumerable:false` flag. And `for..in` only lists enumerable properties. That's why it and the rest of the `Object.prototype` properties are not listed. +Відповідь проста: вони позначені (кажемо стоять під прапорцем) як такі, що не рахуються (not enumerable) так само як і інші властивості в глобальному об’єкті 'Object.prototype'. Прапорець у цьому випадку стоїть як 'enumerable:false', а цикл 'for..in' тільки зчитує властивості, які визначені як такі, що перераховуються. Ось чому і решта властивостей глобального об’єкту 'Object.prototype' не зчитуються також. -```smart header="Almost all other key/value-getting methods ignore inherited properties" -Almost all other key/value-getting methods, such as `Object.keys`, `Object.values` and so on ignore inherited properties. +```smart header="Інші, майже всі, методи по отриманню пар ключ/значення ігнорують успадковані властивості." +Отримання пар ключ/значення в інших методах, таких як: 'Object.keys', 'Object.values' і т.д. ігнорують успадковані властивості. -They only operate on the object itself. Properties from the prototype are *not* taken into account. +Методи працюють тільки на самому об’єкті. Властивості від прототипів *не* беруться до уваги. ``` -## Summary +## Підсумок -- In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`. -- We can use `obj.__proto__` to access it (a historical getter/setter, there are other ways, to be covered soon). -- The object referenced by `[[Prototype]]` is called a "prototype". -- If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype. -- Write/delete operations act directly on the object, they don't use the prototype (assuming it's a data property, not a setter). -- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current object even if they are inherited. -- The `for..in` loop iterates over both its own and its inherited properties. All other key/value-getting methods only operate on the object itself. +- В JavaScript, усі об’єкти мають скриту властивість '[[Prototype]]', яка може бути іншим об’єктом або 'null'. +- Ми можемо використати 'obj.__proto__' для доступу до цієї властивості (це історичний getter/setter; є і інші методи, які будуть розглянуті згодом). +- Об’єкт, на який посилається властивість '[[Prototype]]' називається 'прототип'. +- Якщо ми хочемо прочитати властивості об’єкта 'obj' чи викликаємо метод, який не існує, тоді JavaScript намагається знайти їх в прототипі. +- Операції по запису/видаленню здійснюються безпосередньо на об’єкті. Ці операції не використовують прототипи (припускаючи, що це властивість даних, а не сеттер). +- Якщо ми викликаємо 'obj.method()', і при цьому, 'method' береться з прототипу, ключове слово 'this' вказує на 'obj'. Таким чином, методи завжди працюють з поточним об’єктом, навіть, якщо ці методи успадковані. +- Цикл 'for..in' ітерує як по власних властивостям так і тим, що успадковані. Усі інші методи з отримання пар ключ/значення діють тільки на власних об’єктах. From a12ac5e8f85e9c7f0ea924b7e6fdb8ef15fbfbe0 Mon Sep 17 00:00:00 2001 From: Taras Date: Tue, 3 Aug 2021 22:52:41 +0300 Subject: [PATCH 02/24] Update 1-js/08-prototypes/01-prototype-inheritance/article.md --- 1-js/08-prototypes/01-prototype-inheritance/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 8f5a15dea..4a29f4103 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -56,7 +56,7 @@ alert( rabbit.jumps ); // true В позначеному рядку (*), об’єкт 'animal' визначається як прототип для об’єкта 'rabbit'. -І коли 'alert' намагається прочитати властивість 'rabbit.eats' на рядку позначеному (**), а її там немає, то JavaScript йде по ссилці '[[Prototype]]' та знаходить її в об’єкті 'animal' (дивіться знизу вверх): +І коли 'alert' намагається прочитати властивість 'rabbit.eats' на рядку позначеному (**), а її там немає, то JavaScript йде за посиланням '[[Prototype]]' та знаходить її в об’єкті 'animal' (дивіться знизу вверх): ![](proto-animal-rabbit.svg) From 497d6f6396ece5ee0278d3c4f8ae0e319bcfccc1 Mon Sep 17 00:00:00 2001 From: Volodymyr Sych Date: Tue, 3 Aug 2021 23:34:18 +0300 Subject: [PATCH 03/24] Prototypal inheritance with tasks --- .../1-property-after-delete/solution.md | 6 ++-- .../1-property-after-delete/task.md | 10 +++--- .../2-search-algorithm/solution.md | 6 ++-- .../2-search-algorithm/task.md | 12 +++---- .../3-proto-and-this/solution.md | 8 ++--- .../3-proto-and-this/task.md | 8 ++--- .../4-hamster-proto/solution.md | 32 +++++++++---------- .../4-hamster-proto/task.md | 12 +++---- .../01-prototype-inheritance/article.md | 2 +- 9 files changed, 48 insertions(+), 48 deletions(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md index 6d25a462a..1156af1f1 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md @@ -1,4 +1,4 @@ -1. `true`, taken from `rabbit`. -2. `null`, taken from `animal`. -3. `undefined`, there's no such property any more. +1. `true`, береться з `rabbit`. +2. `null`, береться з `animal`. +3. `undefined`, немає більше такої властивості. diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md index f38fb6f97..65f70bb72 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md @@ -1,12 +1,12 @@ -importance: 5 +Важливість: 5 --- -# Working with prototype +# Робота з прототипами -Here's the code that creates a pair of objects, then modifies them. +Ось код, у якому створюють пару об’єктів і потім в ході виконання їх модифікують. -Which values are shown in the process? +Які значення будуть показані в результаті виконання коду? ```js let animal = { @@ -28,4 +28,4 @@ delete animal.jumps; alert( rabbit.jumps ); // ? (3) ``` -There should be 3 answers. +Повинно бути 3 відповіді. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index a16796f9c..8b529c9cc 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -1,5 +1,5 @@ -1. Let's add `__proto__`: +1. Давайте додамо властивість `__proto__`: ```js run let head = { @@ -27,6 +27,6 @@ alert( table.money ); // undefined ``` -2. In modern engines, performance-wise, there's no difference whether we take a property from an object or its prototype. They remember where the property was found and reuse it in the next request. +2. В сучасних двигунах мов програмування, в інтелектуальнім підході до виконання коду, немає різниці чи ми беремо властивість з самого об’єкту чи його прототипу. Вони запам’ятовують де властивість розташована і використовують це одразу при слідуючому запиті. - For instance, for `pockets.glasses` they remember where they found `glasses` (in `head`), and next time will search right there. They are also smart enough to update internal caches if something changes, so that optimization is safe. +Для прикладу, для `pockets.glasses` вони запам’ятовують де знаходиться властивість `glasses` (в об’єкті `head`), і наступного разу знайдуть її там. Вони також достатньо розумні для поновлення внутрішньої пам’яті якщо вона була змінена, а тому подібна оптимізація є достатньо безпечною. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md index bc2db47fe..698eef768 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md @@ -1,12 +1,12 @@ -importance: 5 +важливість: 5 --- -# Searching algorithm +# Алгоритм пошуку -The task has two parts. +Задача має дві частини. -Given the following objects: +Ми маємо ось такі обєкти: ```js let head = { @@ -27,5 +27,5 @@ let pockets = { }; ``` -1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`). -2. Answer the question: is it faster to get `glasses` as `pockets.glasses` or `head.glasses`? Benchmark if needed. +1. Використайте властивість `__proto__` визначивши прототипи таким чином, щоб отримання властивостей було можливим по ось такому шляху: `pockets` -> `bed` -> `table` -> `head`. Для прикладу, `pockets.pen` повинно отримати значення `3` (було знайдено в `table`), а `bed.glasses` отримує значення `1` (було знайдено в `head`). +2. Дайте відповідь: для отримання властивості `glasses` що буде швидше: визначити її так `pockets.glasses` чи так `head.glasses`? При необхідності зробіть порівняльний тест. diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md index 4d6ea2653..c6c5ab6b8 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md @@ -1,7 +1,7 @@ -**The answer: `rabbit`.** +**Відповідь: `rabbit`.** -That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`. +Це тому, що ключове слово `this` вказує на об’єкт перед крапкою, отже `rabbit.eat()` буде записано в `rabbit`. -Property lookup and execution are two different things. +Пошук метода та його виконання - це дві різні речі. -The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`. +Метод `rabbit.eat` спочатку шукається в прототипі, а потім виконується з умовою `this=rabbit`. diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md index ed8482c07..009e1005e 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md @@ -1,12 +1,12 @@ -importance: 5 +Важливість: 5 --- -# Where does it write? +# Де буде записано? -We have `rabbit` inheriting from `animal`. +Ми маєм об’єкт `rabbit` який успадковує властивості від об’єкта `animal`. -If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`? +Якщо ми викличемо `rabbit.eat()`, який з об’єктів буде записана властивість `full`: в `animal` чи `rabbit`? ```js let animal = { diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index c141b2ecd..b3c3489db 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -1,18 +1,18 @@ -Let's look carefully at what's going on in the call `speedy.eat("apple")`. +Давайте подивимось уважно, що відбувається у виклиці `speedy.eat("apple")`. -1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot). +1. Метод `speedy.eat` знаходиться в (`=hamster`), і вионується з `this=speedy` (об’єкт перед крапкою). -2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found. +2. Потім `this.stomach.push()` повинен знайти властивість `stomach` і викликати `push` на ньому. Він шукає за `stomach` в `this` (`=speedy`), але нічого не знаходить. -3. Then it follows the prototype chain and finds `stomach` in `hamster`. +3. Далі `stomach` йде по ланцюжку прототипів до `hamster`. -4. Then it calls `push` on it, adding the food into *the stomach of the prototype*. +4. Потім він викликає `push` на ньому, додаючи їжу до *шлунку прототипу*. -So all hamsters share a single stomach! +Таким чином, усі хом’ячки мають спільний шлунок! -Both for `lazy.stomach.push(...)` and `speedy.stomach.push()`, the property `stomach` is found in the prototype (as it's not in the object itself), then the new data is pushed into it. +Для обох методів `lazy.stomach.push(...)` і `speedy.stomach.push()`, властивість `stomach` знаходисться в прототипі (бо в самих об’єктах такої властивості немає), яка отрммує нові дані. -Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`: +Будь ласка, зауважте, що така річ не відбувається у випадку простого визначення `this.stomach=`: ```js run let hamster = { @@ -20,7 +20,7 @@ let hamster = { eat(food) { *!* - // assign to this.stomach instead of this.stomach.push + // визначається до this.stomach замість this.stomach.push this.stomach = [food]; */!* } @@ -34,17 +34,17 @@ let lazy = { __proto__: hamster }; -// Speedy one found the food +// Хом’ячок 'Speedy' знайшов їду speedy.eat("apple"); alert( speedy.stomach ); // apple -// Lazy one's stomach is empty +// Шлунок хом’ячка 'Lazy' пустий alert( lazy.stomach ); // ``` -Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object. +Тепер все працює добре, тому що `this.stomach=` не виконує пошук властивості `stomach`. Значення записується прямо в `this` об’єкта. -Also we can totally avoid the problem by making sure that each hamster has their own stomach: +Також, ми можемо узагалі уникнути проблеми визначивши шлунок для кожного хом’ячка окремо, ось так: ```js run let hamster = { @@ -69,12 +69,12 @@ let lazy = { */!* }; -// Speedy one found the food +// Хом’ячок 'Speedy' знайшов їду speedy.eat("apple"); alert( speedy.stomach ); // apple -// Lazy one's stomach is empty +// Шлунок хом’ячка 'Lazy' пустий alert( lazy.stomach ); // ``` -As a common solution, all properties that describe the state of a particular object, like `stomach` above, should be written into that object. That prevents such problems. +Отже, спільним рішенням може бути те, що всі властивості, які описують стан конкретного об’єкта, подібно як `stomach`, повинні бути записані(визначені) в цьому ж самому об’єкті. Це уникне подібної проблеми. diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md index 50171123d..213355900 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md @@ -1,12 +1,12 @@ -importance: 5 +Важливість: 5 --- -# Why are both hamsters full? +# Чому обидва хом’ячка наситились? -We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object. +Ми маємо два хом’ячка (об’єкти): `speedy` та `lazy`, які успадковують властивості від загального об’єкта `hamster`. -When we feed one of them, the other one is also full. Why? How can we fix it? +Коли ми годуємо одного з них, інший також стає ситим. Але чому? Як ми можемо це виправити? ```js run let hamster = { @@ -25,11 +25,11 @@ let lazy = { __proto__: hamster }; -// This one found the food +// Цей хом’ячок знайшов їду speedy.eat("apple"); alert( speedy.stomach ); // apple -// This one also has it, why? fix please. +// Але цей також має їду, чому? Виправте це. alert( lazy.stomach ); // apple ``` diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 8f5a15dea..43d7ba093 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -315,7 +315,7 @@ for(let prop in rabbit) { ![](rabbit-animal-object.svg) -Зауважте одну цікаву річ: звідки метод 'rabbit.hasOwnProperty' забезпечує роботу свого функціоналу, адже властивості на той момент ще не визначені. Дивлячись на ланцюжок успадкувань ми можемо побачити, що отримання властивостей забезпечується 'Object.prototype.hasOwnProperty'. Іншими словами, властивості успадковуються. +Зауважте одну цікаву річ: звідки метод 'rabbit.hasOwnProperty' взявся узагалі, адже він ніде не визначений. Дивлячись на ланцюжок успадкувань ми можемо побачити, що його отримання забезпечується 'Object.prototype.hasOwnProperty'. Іншими словами, він успадковується. ...але чому метод 'hasOwnProperty' не визначає в циклі 'for..in' властивості 'eats' та 'jumps', якщо сам цикл 'for..in' ітерує або проходить по цим успадкованим властивостям? From 53fd54618d26f10137353d24317d6acab1ce3907 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 17:19:13 +0300 Subject: [PATCH 04/24] Update 1-js/08-prototypes/01-prototype-inheritance/article.md --- 1-js/08-prototypes/01-prototype-inheritance/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 4a29f4103..14fd398f9 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -327,7 +327,7 @@ for(let prop in rabbit) { Методи працюють тільки на самому об’єкті. Властивості від прототипів *не* беруться до уваги. ``` -## Підсумок +## Підсумки - В JavaScript, усі об’єкти мають скриту властивість '[[Prototype]]', яка може бути іншим об’єктом або 'null'. - Ми можемо використати 'obj.__proto__' для доступу до цієї властивості (це історичний getter/setter; є і інші методи, які будуть розглянуті згодом). From ccd563974313be4cd5d9555b157a79489fa0f41a Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:49:44 +0300 Subject: [PATCH 05/24] Update 1-js/08-prototypes/01-prototype-inheritance/article.md --- 1-js/08-prototypes/01-prototype-inheritance/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 574ba1bc3..7c4c09980 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -60,7 +60,7 @@ alert( rabbit.jumps ); // true ![](proto-animal-rabbit.svg) -Ми можемо сказати, що 'animal' є прототипом для 'rabbit', або так - об’єкт 'rabbit' успадковує властивості об’єкта 'animal'. +Ми можемо сказати, що "`animal`" є прототипом для `rabbit`, або так -- об’єкт "`rabbit`" успадковує властивості об’єкта `animal`. Якщо 'animal' має багато корисних властивостей та методів, вони стають автоматично доступними для 'rabbit'. Такі властивості називаються 'успадкованими'. From 29337da7f1b5969e90a740312959d52d48319af6 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:50:01 +0300 Subject: [PATCH 06/24] Update 1-js/08-prototypes/01-prototype-inheritance/article.md --- 1-js/08-prototypes/01-prototype-inheritance/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 7c4c09980..669fe8bb4 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -62,7 +62,7 @@ alert( rabbit.jumps ); // true Ми можемо сказати, що "`animal`" є прототипом для `rabbit`, або так -- об’єкт "`rabbit`" успадковує властивості об’єкта `animal`. -Якщо 'animal' має багато корисних властивостей та методів, вони стають автоматично доступними для 'rabbit'. Такі властивості називаються 'успадкованими'. +Якщо `animal` має багато корисних властивостей та методів, вони стають автоматично доступними для `rabbit`. Такі властивості називаються "успадкованими". Також, якщо ми маємо методи в 'animal' то вони можуть бути викликані і в 'rabbit': From bab3934cc14146a06c4cb33fcd36307a876ee68e Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:50:23 +0300 Subject: [PATCH 07/24] Update 1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md --- .../1-property-after-delete/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md index 1156af1f1..c48cbe26d 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md @@ -1,4 +1,4 @@ 1. `true`, береться з `rabbit`. 2. `null`, береться з `animal`. -3. `undefined`, немає більше такої властивості. +3. `undefined`, більше немає такої властивості. From a7fadb37bb778b0622da897b75d0d0c4eddfb448 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:50:38 +0300 Subject: [PATCH 08/24] Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md --- .../01-prototype-inheritance/2-search-algorithm/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index 8b529c9cc..86f6a7992 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -1,5 +1,5 @@ -1. Давайте додамо властивість `__proto__`: +1. Додаймо властивість `__proto__`: ```js run let head = { From b66b4666edf82877e6e90502caa281c4e77ceaab Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:50:57 +0300 Subject: [PATCH 09/24] Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md --- .../01-prototype-inheritance/2-search-algorithm/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index 86f6a7992..9241b259b 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -27,6 +27,6 @@ alert( table.money ); // undefined ``` -2. В сучасних двигунах мов програмування, в інтелектуальнім підході до виконання коду, немає різниці чи ми беремо властивість з самого об’єкту чи його прототипу. Вони запам’ятовують де властивість розташована і використовують це одразу при слідуючому запиті. +2. Для сучасних рушіїв немає різниці, звідки ми беремо властивість -- з самого об’єкта, чи його прототипу. Рушії запам’ятовують де розташована властивість і при повторному запиті одразу її використовують. Для прикладу, для `pockets.glasses` вони запам’ятовують де знаходиться властивість `glasses` (в об’єкті `head`), і наступного разу знайдуть її там. Вони також достатньо розумні для поновлення внутрішньої пам’яті якщо вона була змінена, а тому подібна оптимізація є достатньо безпечною. From 90a2be25ea3d9e67e4ddc03e973d67f14bb69cfc Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:51:09 +0300 Subject: [PATCH 10/24] Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md --- .../01-prototype-inheritance/2-search-algorithm/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index 9241b259b..afce3743a 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -29,4 +29,4 @@ 2. Для сучасних рушіїв немає різниці, звідки ми беремо властивість -- з самого об’єкта, чи його прототипу. Рушії запам’ятовують де розташована властивість і при повторному запиті одразу її використовують. -Для прикладу, для `pockets.glasses` вони запам’ятовують де знаходиться властивість `glasses` (в об’єкті `head`), і наступного разу знайдуть її там. Вони також достатньо розумні для поновлення внутрішньої пам’яті якщо вона була змінена, а тому подібна оптимізація є достатньо безпечною. + Наприклад, для `pockets.glasses` вони запам’ятають, що властивість `glasses` знаходиться в об’єкті `head`, і наступного разу шукатимуть її там. Вони також достатньо розумні для поновлення внутрішньої пам’яті, якщо вона була змінена, а тому подібна оптимізація є достатньо безпечною. From 35d09004a83e5bf9b6c72c553a14b4f5597d5e7e Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:51:20 +0300 Subject: [PATCH 11/24] Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md --- .../01-prototype-inheritance/2-search-algorithm/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md index 698eef768..e725b0d7d 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md @@ -1,4 +1,4 @@ -важливість: 5 +importance: 5 --- From 64484aad1ccfb4a161316e26bffbe14b30ac50a4 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:51:31 +0300 Subject: [PATCH 12/24] Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md --- .../01-prototype-inheritance/2-search-algorithm/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md index e725b0d7d..97b77a7c4 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md @@ -6,7 +6,7 @@ importance: 5 Задача має дві частини. -Ми маємо ось такі обєкти: +Ми маємо ось такі об’єкти: ```js let head = { From 8f81cb81118ae62fdbbe08dddb2b3fe4ecd98174 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:51:41 +0300 Subject: [PATCH 13/24] Update 1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md --- .../01-prototype-inheritance/3-proto-and-this/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md index 009e1005e..a99eac70b 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md @@ -1,4 +1,4 @@ -Важливість: 5 +importance: 5 --- From 01b2cee26a33a06bb7a8f8b0dc2cff55ffaa094a Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:51:51 +0300 Subject: [PATCH 14/24] Update 1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md --- .../01-prototype-inheritance/3-proto-and-this/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md index a99eac70b..d22e676ac 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md @@ -4,7 +4,7 @@ importance: 5 # Де буде записано? -Ми маєм об’єкт `rabbit` який успадковує властивості від об’єкта `animal`. +Ми маємо об’єкт `rabbit`, котрий успадковує властивості від об’єкта `animal`. Якщо ми викличемо `rabbit.eat()`, який з об’єктів буде записана властивість `full`: в `animal` чи `rabbit`? From 82e2352941a1aa0ad9abbcde6563a7daa5698a93 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:00 +0300 Subject: [PATCH 15/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index b3c3489db..fb896dcb4 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -1,4 +1,4 @@ -Давайте подивимось уважно, що відбувається у виклиці `speedy.eat("apple")`. +Подивімося уважно, що відбувається у виклику `speedy.eat("apple")`. 1. Метод `speedy.eat` знаходиться в (`=hamster`), і вионується з `this=speedy` (об’єкт перед крапкою). From 2db53f6afcb9c6490796da9150526e45e35c8878 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:13 +0300 Subject: [PATCH 16/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index fb896dcb4..4383181e7 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -1,6 +1,6 @@ Подивімося уважно, що відбувається у виклику `speedy.eat("apple")`. -1. Метод `speedy.eat` знаходиться в (`=hamster`), і вионується з `this=speedy` (об’єкт перед крапкою). +1. Метод `speedy.eat` знаходиться в прототипі (`=hamster`), і виконується з `this=speedy` (об’єкт перед крапкою). 2. Потім `this.stomach.push()` повинен знайти властивість `stomach` і викликати `push` на ньому. Він шукає за `stomach` в `this` (`=speedy`), але нічого не знаходить. From ea5e7d965b55d766170649e9c63545b6a64413bf Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:27 +0300 Subject: [PATCH 17/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index 4383181e7..8074570ff 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -2,7 +2,7 @@ 1. Метод `speedy.eat` знаходиться в прототипі (`=hamster`), і виконується з `this=speedy` (об’єкт перед крапкою). -2. Потім `this.stomach.push()` повинен знайти властивість `stomach` і викликати `push` на ньому. Він шукає за `stomach` в `this` (`=speedy`), але нічого не знаходить. +2. Потім `this.stomach.push()` повинен знайти властивість `stomach` і викликати `push` на ньому. Він шукає `stomach` в `this` (`=speedy`), але нічого не знаходить. 3. Далі `stomach` йде по ланцюжку прототипів до `hamster`. From cb518cd73afbc2442e123d5bb011a14fa0947f06 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:36 +0300 Subject: [PATCH 18/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index 8074570ff..f2da7000d 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -10,7 +10,7 @@ Таким чином, усі хом’ячки мають спільний шлунок! -Для обох методів `lazy.stomach.push(...)` і `speedy.stomach.push()`, властивість `stomach` знаходисться в прототипі (бо в самих об’єктах такої властивості немає), яка отрммує нові дані. +Для обох методів `lazy.stomach.push(...)` і `speedy.stomach.push()`, властивість `stomach` знаходисться в прототипі (бо в самих об’єктах такої властивості немає), яка отримує нові дані. Будь ласка, зауважте, що така річ не відбувається у випадку простого визначення `this.stomach=`: From 70396aa7ce330b51553e211e6029a3b967876e29 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:43 +0300 Subject: [PATCH 19/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index f2da7000d..22ca3adc0 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -12,7 +12,7 @@ Для обох методів `lazy.stomach.push(...)` і `speedy.stomach.push()`, властивість `stomach` знаходисться в прототипі (бо в самих об’єктах такої властивості немає), яка отримує нові дані. -Будь ласка, зауважте, що така річ не відбувається у випадку простого визначення `this.stomach=`: +Зауважте, що така річ не відбувається у випадку простого визначення `this.stomach=`: ```js run let hamster = { From ffbaa2541fff87c705853b2060c06d0ecbd0edd8 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:50 +0300 Subject: [PATCH 20/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index 22ca3adc0..016b3390a 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -34,7 +34,7 @@ let lazy = { __proto__: hamster }; -// Хом’ячок 'Speedy' знайшов їду +// Хом’ячок 'Speedy' знайшов їжу speedy.eat("apple"); alert( speedy.stomach ); // apple From 65a4ccd7a05eb689e0ca6fabd20140df1cb10e6a Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:52:57 +0300 Subject: [PATCH 21/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md --- .../01-prototype-inheritance/4-hamster-proto/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index 016b3390a..70c7cc017 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -77,4 +77,4 @@ alert( speedy.stomach ); // apple alert( lazy.stomach ); // ``` -Отже, спільним рішенням може бути те, що всі властивості, які описують стан конкретного об’єкта, подібно як `stomach`, повинні бути записані(визначені) в цьому ж самому об’єкті. Це уникне подібної проблеми. +Отже, спільним рішенням може бути те, що всі властивості, які описують стан конкретного об’єкта (подібно як `stomach`), повинні бути записані (визначені) в цьому ж самому об’єкті. Це уникне подібної проблеми. From fc9db58f829662dbbb973f174738b61bb7f23f00 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:53:04 +0300 Subject: [PATCH 22/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md --- .../01-prototype-inheritance/4-hamster-proto/task.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md index 213355900..c97d76b68 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md @@ -1,4 +1,4 @@ -Важливість: 5 +importance: 5 --- @@ -32,4 +32,3 @@ alert( speedy.stomach ); // apple // Але цей також має їду, чому? Виправте це. alert( lazy.stomach ); // apple ``` - From f3d4949a4fc021a872a46ce3afa008d34da723a0 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 20:53:10 +0300 Subject: [PATCH 23/24] Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md --- .../01-prototype-inheritance/4-hamster-proto/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md index c97d76b68..1d29a7a74 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md @@ -29,6 +29,6 @@ let lazy = { speedy.eat("apple"); alert( speedy.stomach ); // apple -// Але цей також має їду, чому? Виправте це. +// Але цей також має їжу, чому? Виправте це. alert( lazy.stomach ); // apple ``` From 6b63291e3504785695e1ce1196c298b562f575f1 Mon Sep 17 00:00:00 2001 From: Taras Date: Wed, 4 Aug 2021 21:31:14 +0300 Subject: [PATCH 24/24] Corrections --- .../01-prototype-inheritance/article.md | 141 +++++++++--------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 669fe8bb4..4a5216569 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -2,21 +2,21 @@ У програмуванні ми часто хочемо щось взяти і доповнити чи розширити. -Наприклад, ми маємо об’єкт 'user' з його властивостями та методами, і хочемо створити 'admin' та 'guest' як дещо змінені варіанти об’єкта 'user'. Тобто ми хочемо повторно використовувати те, що ми маємо в 'user', але також додати ще власні методи і властивості. Іншими словами, просто хочемо збудувати новий об’єкт поверх того, що існує. +Наприклад, ми маємо об’єкт `user` з його властивостями та методами, і хочемо створити `admin` та `guest` як дещо змінені варіанти об’єкта `user`. Тобто ми хочемо повторно використовувати те, що ми маємо в `user`, але також додати ще власні методи і властивості. Інакше кажучи, просто хочемо збудувати новий об’єкт поверх того, що існує. -*успадкування через прототипи* - це те, що нам допоможе в цьому. +*Успадкування через прототипи* -- це те, що нам допоможе в цьому. -## Спеціальна властивість '[[Prototype]]' +## Спеціальна властивість [[Prototype]] -В JavaScript, об’єкти мають спеціальну приховану властивість '[[Prototype]]' (як зазначено в специфікаціях мови), яка може приймати значення: або 'null', або мати посилання на інший об’єкт. Цей об’єкт називається 'прототип': +В JavaScript, об’єкти мають спеціальну приховану властивість `[[Prototype]]` (як зазначено в специфікаціях мови), яка може приймати значення: або `null`, або мати посилання на інший об’єкт. Цей об’єкт називається "прототип": ![prototype](object-prototype-empty.svg) -Коли ми зчитуємо якусь властивість об’єкта 'object', але її не має, JavaScript автоматично бере її з прототипу. В програмуванні це називається 'успадкування через прототипи'. В скорому часі, ми вивчимо багато прикладів такого успадкування, як і створення більш цікавих прикладів, які побудовані на їх основі. +Коли ми зчитуємо якусь властивість об’єкта `object`, але її не має, JavaScript автоматично бере її з прототипу. В програмуванні це називається "успадкування через прототипи". В скорому часі, ми вивчимо багато прикладів такого успадкування, як і створення більш цікавих прикладів, які побудовані на їх основі. -Така властивість '[[Prototype]]' є внутрішньою та прихованою, але є багато шляхів щоб її визначити. +Така властивість `[[Prototype]]` є внутрішньою та прихованою, але є багато шляхів щоб її визначити. -Одним з них є використання спеціального імені '__proto__', наприклад: +Одним з них є використання спеціального імені `__proto__`, наприклад: ```js run let animal = { @@ -31,7 +31,7 @@ rabbit.__proto__ = animal; // тут встановлюємо rabbit.[[Prototype */!* ``` -І тепер, якщо ми зчитуємо властивість з об’єкта 'rabbit', а її немає то JavaScript автоматично візьме її з 'animal'. +І тепер, якщо ми зчитуємо властивість з об’єкта `rabbit`, а її немає, то JavaScript автоматично візьме її з `animal`. Ось ще приклад: @@ -47,31 +47,31 @@ let rabbit = { rabbit.__proto__ = animal; // (*) */!* -// тепер ми можемо знайти обидві властивості в об’єкті 'rabbit': +// тепер ми можемо знайти обидві властивості в об’єкті rabbit: *!* alert( rabbit.eats ); // true (**) */!* alert( rabbit.jumps ); // true ``` -В позначеному рядку (*), об’єкт 'animal' визначається як прототип для об’єкта 'rabbit'. +В позначеному рядку `(*)`, об’єкт `animal` визначається як прототип для об’єкта `rabbit`. -І коли 'alert' намагається прочитати властивість 'rabbit.eats' на рядку позначеному (**), а її там немає, то JavaScript йде за посиланням '[[Prototype]]' та знаходить її в об’єкті 'animal' (дивіться знизу вверх): +І коли `alert` намагається прочитати властивість `rabbit.eats` (рядок позначено `(**)`), а її там немає, то JavaScript йде за посиланням `[[Prototype]]` та знаходить її в об’єкті `animal` (дивіться знизу вверх): ![](proto-animal-rabbit.svg) -Ми можемо сказати, що "`animal`" є прототипом для `rabbit`, або так -- об’єкт "`rabbit`" успадковує властивості об’єкта `animal`. +Ми можемо сказати, що "`animal` є прототипом для `rabbit`", або "об’єкт `rabbit` успадковує властивості об’єкта `animal`". Якщо `animal` має багато корисних властивостей та методів, вони стають автоматично доступними для `rabbit`. Такі властивості називаються "успадкованими". -Також, якщо ми маємо методи в 'animal' то вони можуть бути викликані і в 'rabbit': +Також, якщо ми маємо методи в `animal`, то вони можуть бути викликані і в `rabbit`: ```js run let animal = { eats: true, *!* walk() { - alert("Animal walk"); + alert("Тварина йде"); } */!* }; @@ -81,9 +81,9 @@ let rabbit = { __proto__: animal }; -// тут метод 'walk' береться з прототипу +// тут метод walk береться з прототипу *!* -rabbit.walk(); // отримуємо 'Animal walk' +rabbit.walk(); // отримуємо "Тварина йде" */!* ``` @@ -97,7 +97,7 @@ rabbit.walk(); // отримуємо 'Animal walk' let animal = { eats: true, walk() { - alert("Animal walk"); + alert("Тварина йде"); } }; @@ -115,32 +115,33 @@ let longEar = { */!* }; -// Метод 'walk' беремо з ланцюжка прототипів -longEar.walk(); // отримуємо 'Animal walk' -alert(longEar.jumps); // true (береться з об’єкта 'rabbit') +// Метод walk беремо з ланцюжка прототипів +longEar.walk(); // отримуємо "Тварина йде" +alert(longEar.jumps); // true (береться з об’єкта rabbit) ``` ![](proto-animal-rabbit-chain.svg) -І тепер, якщо ми хочемо взяти метод з об’єкта 'longEar', а його там не має, JavaScript буде шукати його в 'rabbit', далі в 'animal'. +І тепер, якщо ми хочемо взяти метод з об’єкта `longEar`, а його там не має, JavaScript буде шукати його в `rabbit`, далі в `animal`. Існує два обмеження: -1. Посилання через прототипи не може бути замкнено в кільце. JavaScript видасть помилку, якщо ми визначемо '__proto__' в ланцюжку прототипів і замкнем його в кільце. -2. Значення '__proto__' може бути, або посиланням на об'єк, або 'null'. Інші типи значень - ігноруються. +1. Посилання через прототипи не може бути замкнено в кільце. JavaScript видасть помилку, якщо ми визначемо `__proto__` в ланцюжку прототипів і замкнем його в кільце. +2. Значення `__proto__` може бути, або посиланням на об'єк, або `null`. Інші типи значень - ігноруються. -Хоч це і очевидно, але все ж таки: може бути тільки одина властивість '[[Prototype]]'. Об’єкт не може успадковувати властивості та методи від двох прототипів одночасно. +Хоч це і очевидно, але все ж таки: може бути тільки одина властивість `[[Prototype]]`. Об’єкт не може успадковувати властивості та методи від двох прототипів одночасно. -```smart header="'__proto__' є старим і давнім getter/setter для '[[Prototype]]'" -Вважається поширеною помилкою, особливо для початківців, неможливість чітко визначити різницю між двома поняттями '__proto__' та '[[Prototype]]'. +```smart header="`__proto__` є старим і давнім getter/setter для `[[Prototype]]`" +Вважається поширеною помилкою, особливо для початківців, неможливість чітко визначити різницю між двома поняттями `__proto__` та `[[Prototype]]`. -Будь ласка зауважте, що властивість '__proto__' *не є тою самою* властивістю як внутрішня властивість '[[Prototype]]'. Це є 'getter/setter' для '[[Prototype]]'. Пізніше ми побачимо ситуації, коли це важливо, а поки що давайте просто мати це на увазі, примножуючи своє розуміння мови JavaScript. -Властивість '__proto__' вважається трохи застарілим. Вона існує з історичних причин, сучасна мова JavaScript пропонує використовувати функцію 'Object.getPrototypeOf/Object.setPrototypeOf' замість 'get/set' прототипу. Ми також розберем ці функції пізніше. +Будь ласка зауважте, що властивість `__proto__` *не є тою самою* властивістю як внутрішня властивість `[[Prototype]]`. Це є `getter/setter` для `[[Prototype]]`. Пізніше ми побачимо ситуації, коли це важливо, а поки що давайте просто мати це на увазі, примножуючи своє розуміння мови JavaScript. -Згідно специфікаціям мови, '__proto__' повинно тільки підтримуватись в браузерах. Проте насправді, усі середовища, включаючи серверні, підтримують '__proto__', а тому використовувати його можна досить безпечно. +Властивість `__proto__` вважається трохи застарілим. Вона існує з історичних причин, сучасна мова JavaScript пропонує використовувати функцію `Object.getPrototypeOf/Object.setPrototypeOf` замість `get/set` прототипу. Ми також розглянемо ці функції пізніше. -Оскільки позначення '__proto__' більш інтуїтивно зрозуміліше, ми будемо його використовуємо в прикладах. +Згідно зі специфікацією мови, `__proto__` повинно тільки підтримуватись в браузерах. Проте насправді, усі середовища, включаючи серверні, підтримують `__proto__`, а тому використовувати його можна досить безпечно. + +Оскільки позначення `__proto__` більш інтуїтивно зрозуміліше, ми будемо його використовуємо в прикладах. ``` ## Операція по запису/видаленню не застосовується на прототипах @@ -149,13 +150,13 @@ alert(longEar.jumps); // true (береться з об’єкта 'rabbit') А такі операції як запис/видалення, працюють напряму тільки на самому об’єкті. -У прикладі нижче, ми визначаємо власний метод 'walk' для об’єкта 'rabbit': +У прикладі нижче, ми визначаємо власний метод `walk` для об’єкта `rabbit`: ```js run let animal = { eats: true, walk() { - /* цей метод не буде використаний об’єктом 'rabbit' */ + /* цей метод не буде використаний об’єктом rabbit */ } }; @@ -165,20 +166,20 @@ let rabbit = { *!* rabbit.walk = function() { - alert("Rabbit! Bounce-bounce!"); + alert("Кролик! Скік-скік!"); }; */!* -rabbit.walk(); // тут отримаємо 'Rabbit! Bounce-bounce!' +rabbit.walk(); // тут отримаємо 'Кролик! Скік-скік!' ``` -Як тільки ми задаємо метод таким чином 'rabbit.walk()', виклик одразу знайде його на самому об’єкті та виконає без використання такого самого методу, який визначений в прототипі: +Як тільки ми задаємо метод таким чином `rabbit.walk()`, виклик одразу знайде його на самому об’єкті та виконає без використання такого самого методу, який визначений в прототипі: ![](proto-animal-rabbit-walk-2.svg) Властивості 'Accessor' є винятком, оскільки присвоєння обробляється функцією встановлення (через 'setter'). Отже, запис у таку властивість насправді те саме, що виклик функції. -З цієї причини 'admin.fullName' коректно працює в коді, що показаний нижче: +З цієї причини `admin.fullName` коректно працює в коді, що показаний нижче: ```js run let user = { @@ -204,34 +205,34 @@ alert(admin.fullName); // John Smith (*) // відпрацьовує setter admin.fullName = "Alice Cooper"; // (**) -alert(admin.fullName); // Alice Cooper, стан об’єкта 'admin' було змінено -alert(user.fullName); // John Smith, стан об’єкта 'user' захищено +alert(admin.fullName); // Alice Cooper, стан об’єкта admin було змінено +alert(user.fullName); // John Smith, стан об’єкта user захищено ``` -Тут на рядку позначеному (*), властивість 'admin.fullName' викликається через 'getter' визначений в прототипі 'user'. А на рядку позначеному (**) властивість задається через setter, який також визначений в прототипі. +Тут на рядку позначеному `(*)`, властивість `admin.fullName` викликається через getter, визначений в прототипі `user`. А на рядку позначеному `(**)` властивість задається через setter, який також визначений в прототипі. ## Значення ключового слова "this" -Цікаве питання може виникнути в прикладі вище: яке значення ключового слова 'this' всередині 'set fullName(value)'? Де визначаютья властивості 'this.name' та 'this.surname': в об’єкті 'user' чи 'admin'? +Цікаве питання може виникнути в прикладі вище: яке значення ключового слова `this` всередині `set fullName(value)`? Де визначаютья властивості `this.name` та `this.surname`: в об’єкті `user` чи `admin`? -Відповідь проста: на 'this' не впливає прототип узагалі. +Відповідь проста: на `this` не впливає прототип узагалі. -**Незалежно від того, де метод визначений: в об’єкті чи його прототипі, ключове слово 'this' завжди вказує на об’єкт перед крапкою.** +**Незалежно від того, де метод визначений: в об’єкті чи його прототипі, ключове слово `this` завжди вказує на об’єкт перед крапкою.** -Таким чином, виклик в методі 'set' виразу 'admin.fullName=' буде брати як 'this' значення властивостей з об’єкту 'admin' а не 'user'. +Таким чином, виклик в методі `set` виразу `admin.fullName=` буде брати як `this` значення властивостей з об’єкту `admin` а не `user`. В дійсності це є дуже важлива річ бо наприклад, ми можемо мати дуже великий об’єкт з багатьма методами, і також маємо об’єкти, які успадковують властивості або методи від того великого об’єкту. Коли успадковані методи викликаються на стороні об’єктів, що їх успадкували, вони можуть змінювати тільки свої стани а не стан того великого об’єкту. -У цьому прикладі, об’єкт 'animal' представляє "набір методів", а об’єкт 'rabbit' може використовувати якісь з цих методів. +У цьому прикладі, об’єкт `animal` представляє "набір методів", а об’єкт `rabbit` може використовувати якісь з цих методів. -Виклик 'rabbit.sleep()' встановлює 'this.isSleeping' в об’єкті 'rabbit': +Виклик `rabbit.sleep()` встановлює `this.isSleeping` в об’єкті `rabbit`: ```js run -// об’єкт 'animal' має набір методів has +// об’єкт animal має набір методів has let animal = { walk() { if (!this.isSleeping) { - alert(`I walk`); + alert(`Я ходжу`); } }, sleep() { @@ -240,7 +241,7 @@ let animal = { }; let rabbit = { - name: "White Rabbit", + name: "Білий кролик", __proto__: animal }; @@ -255,13 +256,13 @@ alert(animal.isSleeping); // undefined (немає такого методу в ![](proto-animal-rabbit-walk-3.svg) -Якщо ми маємо інші об’єкти: 'bird', 'snake', і т.д, які успадковують методи від об’єкта 'animal'. Кожний раз, при виклику будь-якого методу, ключове слово 'this' буде вказувати на той об’єкт, на стороні якого був викликаний цей метод, а не на об’єкт 'animal'. Отже, коли ми записуємо будь-які дані в 'this', вони зберігаються в об’єктах на які і вказує 'this'. +Якщо ми маємо інші об’єкти: `bird`, `snake` тощо, які успадковані від об’єкта `animal`, вони також будуть мати доступ до методів `animal`. Кожний раз, при виклику будь-якого методу, ключове слово `this` буде вказувати на той об’єкт, на стороні якого був викликаний цей метод, а не на об’єкт `animal`. Отже, коли ми записуємо будь-які дані в `this`, вони зберігаються в об’єктах на які і вказує `this`. Як результат, методи можуть успадковуватись (передаватись), але стани об’єктів - не можуть. -## цикл for..in +## Цикл for..in -Цикл 'for..in' може проходитись по успадкованим властивостям також. +Цикл `for..in` також може проходитись по успадкованим властивостям. Наприклад: @@ -276,19 +277,19 @@ let rabbit = { }; *!* -// Object.keys повертає тільки влвасні ключі +// Object.keys повертає тільки власні ключі alert(Object.keys(rabbit)); // jumps */!* *!* -// Цикл for..in loops повертає як власні так і успадковані ключі +// Цикл for..in повертає як власні так і успадковані ключі for(let prop in rabbit) alert(prop); // jumps, потім eats */!* ``` -Якщо це не те, що нам потрібно, і ми б хотіли виключити отримання успадкованих значень, існує вбудований метод '[obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty)', який повертає 'true' якщо 'obj' має тільки власні (не успадковані) властивості. +Якщо це не те, що нам потрібно, і ми б хотіли виключити отримання успадкованих значень, існує вбудований метод [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty), який повертає `true` якщо `obj` має тільки власні (не успадковані) властивості. -Отже, ми можемо відфільтрувати успадковані властивості (чи щось зробити з ними інше ): +Отже, ми можемо відфільтрувати успадковані властивості (чи щось зробити з ними інше): ```js run let animal = { @@ -304,35 +305,35 @@ for(let prop in rabbit) { let isOwn = rabbit.hasOwnProperty(prop); if (isOwn) { - alert(`Our: ${prop}`); // Our: jumps + alert(`Наш: ${prop}`); // Наш: jumps } else { - alert(`Inherited: ${prop}`); // Inherited: eats + alert(`Успадковано: ${prop}`); // Успадковано: eats } } ``` -У цьому прикладі ми маємо наступний ланцюжок: 'rabbit' успадковує властивості від об’єкта 'animal', який, у свою чергу, успадковує властивості від глобального 'Object.prototype' (тому що 'animal' є літералом об’єкта '{...}' за замовчуванням) і на самому верху маємо 'null': +У цьому прикладі ми маємо наступний ланцюжок: `rabbit` успадковує властивості від об’єкта `animal`, який, у свою чергу, успадковує властивості від глобального `Object.prototype` (тому що `animal` типово є літералом об’єкта `{...}`) і на самому верху маємо `null`: ![](rabbit-animal-object.svg) -Зауважте одну цікаву річ: звідки метод 'rabbit.hasOwnProperty' взявся узагалі, адже він ніде не визначений. Дивлячись на ланцюжок успадкувань ми можемо побачити, що його отримання забезпечується 'Object.prototype.hasOwnProperty'. Іншими словами, він успадковується. +Зауважте одну цікаву річ: звідки взагалі взявся метод `rabbit.hasOwnProperty`? Ми його не визначали. Дивлячись на ланцюжок успадкувань ми можемо побачити, що його визначення йде від `Object.prototype.hasOwnProperty`. Інакше кажучи, він успадковується. -...але чому метод 'hasOwnProperty' не визначає в циклі 'for..in' властивості 'eats' та 'jumps', якщо сам цикл 'for..in' ітерує або проходить по цим успадкованим властивостям? +...але чому метод `hasOwnProperty` не визначає в циклі `for..in` властивості `eats` та `jumps`, якщо сам цикл `for..in` ітерує або проходить по цим успадкованим властивостям? -Відповідь проста: вони позначені (кажемо стоять під прапорцем) як такі, що не рахуються (not enumerable) так само як і інші властивості в глобальному об’єкті 'Object.prototype'. Прапорець у цьому випадку стоїть як 'enumerable:false', а цикл 'for..in' тільки зчитує властивості, які визначені як такі, що перераховуються. Ось чому і решта властивостей глобального об’єкту 'Object.prototype' не зчитуються також. +Відповідь проста: вони позначені (кажемо стоять під прапорцем) як такі, що не рахуються (not enumerable) так само як і інші властивості в глобальному об’єкті `Object.prototype`. Прапорець у цьому випадку стоїть як `enumerable:false`, а цикл `for..in` тільки зчитує властивості, які визначені як такі, що перераховуються. Ось чому і решта властивостей глобального об’єкту `Object.prototype` не зчитуються також. -```smart header="Інші, майже всі, методи по отриманню пар ключ/значення ігнорують успадковані властивості." -Отримання пар ключ/значення в інших методах, таких як: 'Object.keys', 'Object.values' і т.д. ігнорують успадковані властивості. +```smart header="Майже всі інші методи по отриманню пар ключ/значення ігнорують успадковані властивості" +Отримання пар ключ/значення в інших методах, таких як: `Object.keys`, `Object.values` тощо, ігнорують успадковані властивості. Методи працюють тільки на самому об’єкті. Властивості від прототипів *не* беруться до уваги. ``` ## Підсумки -- В JavaScript, усі об’єкти мають скриту властивість '[[Prototype]]', яка може бути іншим об’єктом або 'null'. -- Ми можемо використати 'obj.__proto__' для доступу до цієї властивості (це історичний getter/setter; є і інші методи, які будуть розглянуті згодом). -- Об’єкт, на який посилається властивість '[[Prototype]]' називається 'прототип'. -- Якщо ми хочемо прочитати властивості об’єкта 'obj' чи викликаємо метод, який не існує, тоді JavaScript намагається знайти їх в прототипі. -- Операції по запису/видаленню здійснюються безпосередньо на об’єкті. Ці операції не використовують прототипи (припускаючи, що це властивість даних, а не сеттер). -- Якщо ми викликаємо 'obj.method()', і при цьому, 'method' береться з прототипу, ключове слово 'this' вказує на 'obj'. Таким чином, методи завжди працюють з поточним об’єктом, навіть, якщо ці методи успадковані. -- Цикл 'for..in' ітерує як по власних властивостям так і тим, що успадковані. Усі інші методи з отримання пар ключ/значення діють тільки на власних об’єктах. +- В JavaScript, усі об’єкти мають приховану властивість `[[Prototype]]`, яка може бути іншим об’єктом або `null`. +- Ми можемо використати `obj.__proto__` для доступу до цієї властивості (це історичний getter/setter; є й інші методи, які розглянемо згодом). +- Об’єкт, на який посилається властивість `[[Prototype]]` називається "прототип". +- Якщо ми хочемо прочитати властивості об’єкта `obj` чи викликаємо метод, який не існує, тоді JavaScript намагається знайти їх в прототипі. +- Операції по запису/видаленню здійснюються безпосередньо на об’єкті. Ці операції не використовують прототипи (припускаючи, що це властивість даних, а не setter). +- Якщо ми викликаємо `obj.method()`, і при цьому, `method` береться з прототипу, ключове слово `this` вказує на `obj`. Таким чином, методи завжди працюють з поточним об’єктом, навіть, якщо ці методи успадковані. +- Цикл `for..in` ітерує як по власних властивостям так і по успадкованих. Усі інші методи з отримання пар ключ/значення діють тільки на власних об’єктах.