Skip to content

Prototypal inheritance #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4c9ecb9
Prototypal inheritance
VolodymyrSSS Jul 29, 2021
a12ac5e
Update 1-js/08-prototypes/01-prototype-inheritance/article.md
tarasyyyk Aug 3, 2021
497d6f6
Prototypal inheritance with tasks
VolodymyrSSS Aug 3, 2021
13a3867
Merge branch 'master' of https://github.com/VolodymyrSSS/uk.javascrip…
VolodymyrSSS Aug 3, 2021
53fd546
Update 1-js/08-prototypes/01-prototype-inheritance/article.md
tarasyyyk Aug 4, 2021
7fb075d
Merge branch 'master' of https://github.com/VolodymyrSSS/uk.javascrip…
VolodymyrSSS Aug 4, 2021
ccd5639
Update 1-js/08-prototypes/01-prototype-inheritance/article.md
tarasyyyk Aug 4, 2021
29337da
Update 1-js/08-prototypes/01-prototype-inheritance/article.md
tarasyyyk Aug 4, 2021
bab3934
Update 1-js/08-prototypes/01-prototype-inheritance/1-property-after-d…
tarasyyyk Aug 4, 2021
a7fadb3
Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm…
tarasyyyk Aug 4, 2021
b66b466
Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm…
tarasyyyk Aug 4, 2021
90a2be2
Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm…
tarasyyyk Aug 4, 2021
35d0900
Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm…
tarasyyyk Aug 4, 2021
64484aa
Update 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm…
tarasyyyk Aug 4, 2021
8f81cb8
Update 1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/t…
tarasyyyk Aug 4, 2021
01b2cee
Update 1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/t…
tarasyyyk Aug 4, 2021
82e2352
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
2db53f6
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
ea5e7d9
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
cb518cd
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
70396aa
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
ffbaa25
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
65a4ccd
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/so…
tarasyyyk Aug 4, 2021
fc9db58
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/ta…
tarasyyyk Aug 4, 2021
f3d4949
Update 1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/ta…
tarasyyyk Aug 4, 2021
6b63291
Corrections
tarasyyyk Aug 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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`, більше немає такої властивості.
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -28,4 +28,4 @@ delete animal.jumps;
alert( rabbit.jumps ); // ? (3)
```

There should be 3 answers.
Повинно бути 3 відповіді.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

1. Let's add `__proto__`:
1. Додаймо властивість `__proto__`:

```js run
let head = {
Expand Down Expand Up @@ -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`, і наступного разу шукатимуть її там. Вони також достатньо розумні для поновлення внутрішньої пам’яті, якщо вона була змінена, а тому подібна оптимізація є достатньо безпечною.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Searching algorithm
# Алгоритм пошуку

The task has two parts.
Задача має дві частини.

Given the following objects:
Ми маємо ось такі об’єкти:

```js
let head = {
Expand All @@ -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`? При необхідності зробіть порівняльний тест.
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 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 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
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 = {
stomach: [],

eat(food) {
*!*
// assign to this.stomach instead of this.stomach.push
// визначається до this.stomach замість this.stomach.push
this.stomach = [food];
*/!*
}
Expand All @@ -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 ); // <nothing>
```

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 = {
Expand All @@ -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 ); // <nothing>
```

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`), повинні бути записані (визначені) в цьому ж самому об’єкті. Це уникне подібної проблеми.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 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 = {
Expand All @@ -25,11 +25,10 @@ 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
```

Loading