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 d22e676ac..ae73f5204 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 @@ -6,7 +6,7 @@ importance: 5 Ми маємо об’єкт `rabbit`, котрий успадковує властивості від об’єкта `animal`. -Якщо ми викличемо `rabbit.eat()`, який з об’єктів буде записана властивість `full`: в `animal` чи `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 70c7cc017..4dcd6da2c 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 @@ -20,7 +20,7 @@ let hamster = { eat(food) { *!* - // визначається до this.stomach замість this.stomach.push + // визначається до `this.stomach` замість `this.stomach.push` this.stomach = [food]; */!* } @@ -39,7 +39,7 @@ speedy.eat("apple"); alert( speedy.stomach ); // apple // Шлунок хом’ячка 'Lazy' пустий -alert( lazy.stomach ); // +alert( lazy.stomach ); // <нічого> ``` Тепер все працює добре, тому що `this.stomach=` не виконує пошук властивості `stomach`. Значення записується прямо в `this` об’єкта. @@ -69,12 +69,12 @@ let lazy = { */!* }; -// Хом’ячок 'Speedy' знайшов їду -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// Хом’ячок `Speedy` знайшов їжу +speedy.eat("яблуко"); +alert( speedy.stomach ); // яблуко -// Шлунок хом’ячка 'Lazy' пустий -alert( lazy.stomach ); // +// Шлунок хом’ячка `Lazy` пустий +alert( lazy.stomach ); // <нічого> ``` Отже, спільним рішенням може бути те, що всі властивості, які описують стан конкретного об’єкта (подібно як `stomach`), повинні бути записані (визначені) в цьому ж самому об’єкті. Це уникне подібної проблеми. diff --git a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md index ebbdf3a7c..7a5694d4d 100644 --- a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md +++ b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md @@ -1,20 +1,20 @@ -Answers: +Відповідь: 1. `true`. - The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones. + Визначення `Rabbit.prototype` встановлює властивість `[[Prototype]]` для новоствореного об’єкта, але це жодним чином не впливає на вже існуючий об’єкт. 2. `false`. - Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`. + Об’єкти призначаються шляхом посилання на них. Об’єкт з властивістю `Rabbit.prototype` не дублюється, це є той самий об’єкт на який посилаються як через `Rabbit.prototype` так і через властивість `[[Prototype]]` об’єкта `rabbit`. - So when we change its content through one reference, it is visible through the other one. + А отже, коли ми змінюємо контент такого об’єкта через посилання, такі зміни стають видимі і через інші посилання. 3. `true`. - All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect. + Усі `delete` операції застосовуються безпосередньо на самому об'єкті. Тут `delete rabbit.eats` намагається видалити властивість `eats` з об’єкта `rabbit`, але такої властивості немає. А тому така операція не має ніякого ефекту. 4. `undefined`. - The property `eats` is deleted from the prototype, it doesn't exist any more. + Властивість `eats` видалена з прототипу, вона більше не існує. diff --git a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md index 2838c125a..d0bb4358c 100644 --- a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md +++ b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Changing "prototype" +# Заміна властивості "prototype" -In the code below we create `new Rabbit`, and then try to modify its prototype. +В коді, що показаний нижче, ми створюємо об’єкт `new Rabbit` і потім міняємо його прототип. -In the start, we have this code: +На початку, маємо цей код: ```js run function Rabbit() {} @@ -20,7 +20,7 @@ alert( rabbit.eats ); // true ``` -1. We added one more string (emphasized). What will `alert` show now? +1. Ми додали ще рядок коду (виділений). Що покаже тепер `alert`? ```js function Rabbit() {} @@ -37,7 +37,7 @@ alert( rabbit.eats ); // true alert( rabbit.eats ); // ? ``` -2. ...And if the code is like this (replaced one line)? +2. ...А якщо маємо такий код (з видаленим рядком коду)? ```js function Rabbit() {} @@ -54,7 +54,7 @@ alert( rabbit.eats ); // true alert( rabbit.eats ); // ? ``` -3. And like this (replaced one line)? +3. А якщо так (також з видаленим рядком коду)? ```js function Rabbit() {} @@ -71,7 +71,7 @@ alert( rabbit.eats ); // true alert( rabbit.eats ); // ? ``` -4. The last variant: +4. І останній варіант: ```js function Rabbit() {} diff --git a/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md index 372d50dd6..558b03843 100644 --- a/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md +++ b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md @@ -1,6 +1,6 @@ -We can use such approach if we are sure that `"constructor"` property has the correct value. +Так, ми можемо використовувати такий підхід якщо ми впевнені, що властивість `"constructor"` має правильне значення. -For instance, if we don't touch the default `"prototype"`, then this code works for sure: +Для прикладу, якщо ми не чіпаємо властивість за замовчуванням `"prototype"`, тоді цей код буде працювати правильно: ```js run function User(name) { @@ -10,14 +10,14 @@ function User(name) { let user = new User('John'); let user2 = new user.constructor('Pete'); -alert( user2.name ); // Pete (worked!) +alert( user2.name ); // Pete (працює!) ``` -It worked, because `User.prototype.constructor == User`. +Код працює, тому що `User.prototype.constructor == User`. -..But if someone, so to speak, overwrites `User.prototype` and forgets to recreate `constructor` to reference `User`, then it would fail. +..Але якщо хтось, якщо можна так виразитись, перезапише `User.prototype` і забуде додати властивість `constructor` в посиланні властивості об’єкта `User`, тоді цей код не буде працювати правильно. -For instance: +Наприклад: ```js run function User(name) { @@ -33,17 +33,17 @@ let user2 = new user.constructor('Pete'); alert( user2.name ); // undefined ``` -Why `user2.name` is `undefined`? +Чому `user2.name` є `undefined`? -Here's how `new user.constructor('Pete')` works: +Ось тут пояснення як `new user.constructor('Pete')` працює: -1. First, it looks for `constructor` in `user`. Nothing. -2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has no `constructor` (because we "forgot" to set it right!). -3. Going further up the chain, `User.prototype` is a plain object, its prototype is the built-in `Object.prototype`. -4. Finally, for the built-in `Object.prototype`, there's a built-in `Object.prototype.constructor == Object`. So it is used. +1. Спочатку, здійснюється пошук у властивості `constructor` об’єкта `user`. Нічого не знаходять. +2. Потім переключаються на ланцюжок прототипу. Прототипом для об’єкта `user` є `User.prototype`, і він також не має властивості `constructor` (тому що ми "забули" визначити його правильним чином!). +3. Йдучи далі по ланцюжку прототипу, визначаємо, що `User.prototype` є простий об’єкт, його прототипом є вбудований глобальний `Object.prototype`. +4. Врешті, для вбудованого `Object.prototype`, є вбудований конструктор глобального об’єкта `Object.prototype.constructor == Object` от він і використовується. -Finally, at the end, we have `let user2 = new Object('Pete')`. +Таким чином, в кінці, ми отримуємо `let user2 = new Object('Pete')`. -Probably, that's not what we want. We'd like to create `new User`, not `new Object`. That's the outcome of the missing `constructor`. +Ймовірно, це не те, що нам потрібно. Ми би хотіли стоврити `new User`, а не `new Object`. Це і є наслідки пропуску властивості `constructor`. -(Just in case you're curious, the `new Object(...)` call converts its argument to an object. That's a theoretical thing, in practice no one calls `new Object` with a value, and generally we don't use `new Object` to make objects at all). \ No newline at end of file +(на випадок, якщо вас зацікавить, виклик `new Object(...)` перетворює його аргументи на об’єкт. Це в теорії, але на практиці ніхто не викликає `new Object` з аргументами; і загалом, не використовується узагалі `new Object` для створення нових об’єктів). \ No newline at end of file diff --git a/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md index 934f3470b..fd762b072 100644 --- a/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md +++ b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md @@ -2,14 +2,14 @@ importance: 5 --- -# Create an object with the same constructor +# Створення нового об’єкта з одинаковим конструктором -Imagine, we have an arbitrary object `obj`, created by a constructor function -- we don't know which one, but we'd like to create a new object using it. +Уявіть собі, у нас є довільний об’єкт `obj`, який створений функцією-конструктором -- ми не знаємо яким саме конструктором, але потрібно створити новий об’єкт використовуючи той самий конструктор. -Can we do it like that? +Чи можна створити новий об’єкт ось так? ```js let obj2 = new obj.constructor(); ``` -Give an example of a constructor function for `obj` which lets such code work right. And an example that makes it work wrong. +Покажіть приклад функції-конструктора для обєкта `obj`, який забезпечить правильну роботу такого коду, а також приклад, який, при такому коді, працює неправельно. diff --git a/1-js/08-prototypes/02-function-prototype/article.md b/1-js/08-prototypes/02-function-prototype/article.md index b1ef51826..f1ab37da1 100644 --- a/1-js/08-prototypes/02-function-prototype/article.md +++ b/1-js/08-prototypes/02-function-prototype/article.md @@ -1,18 +1,18 @@ # F.prototype -Remember, new objects can be created with a constructor function, like `new F()`. +Як відомо, ми можемо створювати нові об’єкти за допомогою функції-конструктора, ось так `new F()`. -If `F.prototype` is an object, then the `new` operator uses it to set `[[Prototype]]` for the new object. +Якщо розглядати `F.prototype` як властивість об’єкта, то оператор `new` автоматично створює приховану властивість `[[Prototype]]` для новоствореного об’єкта. ```smart -JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language. +JavaScript мала можливість успадкування властивостей через прототипи ще від самого початку її створення. Це було одним з головних особливостей мови. -But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it. +Але в ті часи, не було прямого доступу до прототипів. Тільки одна річ, яка працювала надійно, була властивість функції-конструктора `"prototype"` , яка і описана в цій главі. Ось чому ще існує багато коду де цю властивість використовують. ``` -Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name. +Зауважте, що `F.prototype` тут означає звичайну властивість, яку назвали `"prototype"` в об’єкті `F`. Це звучить дуже співзвучно з терміном "prototype", але тут це означає всього лиш звичайне ім’я властивості. -Here's the example: +Ось приклад: ```js run let animal = { @@ -32,65 +32,65 @@ let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal alert( rabbit.eats ); // true ``` -Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`". +Вираз `Rabbit.prototype = animal` дослівно означає наступне: "коли `new Rabbit` створено, його властивість `[[Prototype]]` посилається на об’єкт `animal`". -That's the resulting picture: +Ось кінцева картинка: ![](proto-constructor-animal-rabbit.svg) -On the picture, `"prototype"` is a horizontal arrow, meaning a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`. +На картинці, `"prototype"` що показана горизонтальною стрілкою, це звичайна властивість, а `[[Prototype]]`показана вертикальною, що означає `rabbit` успадковує властивості від свого прототипа `animal`. -```smart header="`F.prototype` only used at `new F` time" -`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object. +```smart header="`F.prototype` використовується тільки у разі використання функції-конструктора `new F`" +Властивість `F.prototype` використовується коли буде викликано `new F`, і створює властивість `[[Prototype]]` для нового об’єкта. -If, after the creation, `F.prototype` property changes (`F.prototype = `), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one. +Якщо властивість `F.prototype` після створення змінюється (`F.prototype = `), тоді і новий об’єкт який створюється функцією-конструктором `new F` буде мати посилання `[[Prototype]]` на інший об’єкт, а в раніше створених об’єктах є свої прототипи які були визначені ще при їх створенні. ``` -## Default F.prototype, constructor property +## Типове значення F.prototype, властивості конструктора -Every function has the `"prototype"` property even if we don't supply it. +Кожна функція має властивість `"prototype"` навіть якщо ми цю властивість самі не прописуємо. Тобто вона існує за замовчуванням, або ця властивість є типовою. -The default `"prototype"` is an object with the only property `constructor` that points back to the function itself. +В свою чергу, така типова властивість `"prototype"` представляє собою об’єкт, який має єдину властивість з назвою `constructor`, що зворотньо посилається на назву самої функції-конструктора. -Like this: +Ось як тут: ```js function Rabbit() {} -/* default prototype +/* властивість створена за замовчуванням Rabbit.prototype = { constructor: Rabbit }; */ ``` ![](function-prototype-constructor.svg) -We can check it: +Можемо перевірити це: ```js run function Rabbit() {} -// by default: +// за замовчуванням: // Rabbit.prototype = { constructor: Rabbit } alert( Rabbit.prototype.constructor == Rabbit ); // true ``` -Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`: +Отже, якщо ми нічого не робимо з властивістю `constructor` то вона є доступна для всіх об’єктів rabbits через `[[Prototype]]`: ```js run function Rabbit() {} -// by default: +// за замовчуванням: // Rabbit.prototype = { constructor: Rabbit } -let rabbit = new Rabbit(); // inherits from {constructor: Rabbit} +let rabbit = new Rabbit(); // успадковує від {constructor: Rabbit} -alert(rabbit.constructor == Rabbit); // true (from prototype) +alert(rabbit.constructor == Rabbit); // true (від прототипу) ``` ![](rabbit-prototype-constructor.svg) -We can use `constructor` property to create a new object using the same constructor as the existing one. +Ми можемо використовувати властивість `constructor` для створення нових об’єктів використовуючи той самий конструктор, який вже існує. -Like here: +Як тут: ```js run function Rabbit(name) { @@ -105,17 +105,17 @@ let rabbit2 = new rabbit.constructor("Black Rabbit"); */!* ``` -That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind. +Це дуже практично у випадку наявності об’єкта, але не знаємо за допомогою якого саме конструктора той об’єкт був створений (для прикладу який був імпортований з якоїсь бібліотеки), а нам потрібно створити новий об’єкт по типу того, що вже існує. -But probably the most important thing about `"constructor"` is that... +Але самим важливим моментом щодо `"constructor"` є те, що... -**...JavaScript itself does not ensure the right `"constructor"` value.** +**...Сама мова JavaScript не забезпечує правильного значення `"constructor"`.** -Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us. +Так, воно існує за замовчуванням у властивостях `"prototype"` для функцій, але це все, що є. Те, що стається з `"constructor"` пізніше, цілковито залежить від нас самих. -In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it. +А іменно, якщо ми замінимо дефолтне значення на якесь інше, тоді не буде ніякого `"constructor"` в ньому. -For instance: +Наприклад: ```js run function Rabbit() {} @@ -129,18 +129,18 @@ alert(rabbit.constructor === Rabbit); // false */!* ``` -So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole: +Отже, щоб мати правильний `"constructor"` ми можемо чи додавати, чи видаляти властивості у дефолтному `"prototype"` замість того, щоб її цілковито заміняти: ```js function Rabbit() {} -// Not overwrite Rabbit.prototype totally -// just add to it +// Тут ми не заміняємо цілковито властивість Rabbit.prototype +// а просто додаємо до неї Rabbit.prototype.jumps = true -// the default Rabbit.prototype.constructor is preserved +// а тому дефолтне Rabbit.prototype.constructor зберігається ``` -Or, alternatively, recreate the `constructor` property manually: +чи по іншоу, відновлюємо `constructor` ручним способом: ```js Rabbit.prototype = { @@ -150,26 +150,26 @@ Rabbit.prototype = { */!* }; -// now constructor is also correct, because we added it +// і тепер, constructor є також правельним, мому що ми його додали вручну ``` -## Summary +## Підсумок -In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it. +В цьому розділі було коротко описано шлях для встановлення скритої властивості `[[Prototype]]` об’єктів, які були створені за допомогою функції-конструктором. Пізніше, буде надано більше прикладів коду, які покладаються на ці властивості. -Everything is quite simple, just a few notes to make things clear: +Все є простим, тільки додамо декілька штрихів для того щоб усе було зрозуміло: -- The `F.prototype` property (don't mistake it for `[[Prototype]]`) sets `[[Prototype]]` of new objects when `new F()` is called. -- The value of `F.prototype` should be either an object or `null`: other values won't work. -- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`. +- Властивість об’єкта `F.prototype` (ні в якому разі не `[[Prototype]]`) встановлює скриту властивість `[[Prototype]]` нового об’єкта, тільки тоді, коли буде викликана через `new F()`. +- Значення властивості `F.prototype` може бути, або посиланням на об’єкт, або `null`: інші значення не працюють. +- Тільки властивість `"prototype"`має такий спеціальний ефект: може встановлюватись в конструкторі та може викликатись через оператор `new`. -On regular objects the `prototype` is nothing special: +У звичайних об’єктах властивість `prototype` не є чимось спеціальним: ```js let user = { name: "John", - prototype: "Bla-bla" // no magic at all + prototype: "Bla-bla" // немає ніякої магії }; ``` -By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property. +За замовчуванням, усі функції мають `F.prototype = { constructor: F }`, і ми можемо отримати конструктор об’єкта через його властивість `"constructor"`.