From 22d62ecf1a908c666c2014603e79eaaafcce0c66 Mon Sep 17 00:00:00 2001 From: Andrii Hrushetskyi Date: Sun, 16 Feb 2025 21:10:18 +0100 Subject: [PATCH 1/2] refactored translation of chapter 01-04-09 (object-toprimitive) **For article 01-04-09 object-toprimitive** There were so much mistakes, that article was completely wrong for understaing. I understood that topic only after I've read English version. --- .../09-object-toprimitive/article.md | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/1-js/04-object-basics/09-object-toprimitive/article.md b/1-js/04-object-basics/09-object-toprimitive/article.md index 4916a24da..df767834d 100644 --- a/1-js/04-object-basics/09-object-toprimitive/article.md +++ b/1-js/04-object-basics/09-object-toprimitive/article.md @@ -5,28 +5,28 @@ JavaScript не дозволяє налаштувати те, як працюють оператори з об’єктами. На відміну від деяких інших мов програмування, таких як Ruby або C++, ми не можемо реалізувати спеціальний об’єктний метод для обробки додавання (або інших операторів). -У разі таких операцій, об’єкти автоматично перетворюються на примітиви, а потім операція здійснюється над цими примітивами та повертає результат у вигляді примітивного значення. +У разі таких операцій, об’єкти автоматично перетворюються на примітиви, а потім операція здійснюється над цими примітивами та повертає результат саме у вигляді примітивного значення. Це важливе обмеження, оскільки результат `obj1 + obj2` (або інша математична операція) не може бути іншим об’єктом! -Наприклад, ми не можемо зробити об’єкти, що представляють вектори або матриці (або досягнення або що завгодно) та додати їх і очікувати, що "сплюсованим" результатом буде об’єкт. Автоматично такі архітектурні особливості недоступні. +Наприклад, ми не можемо зробити об’єкти, що представляють вектори або матриці (або досягнення або що завгодно) та додати їх і очікувати, що "сплюсованим" результатом буде об’єкт. Такі архітектурні особливості автоматично недоступні. -Отже, оскільки ми не можемо технічно нічого з цим зробити, у реальних проектах немає жодних математичних дій з об’єктами. Коли це трапляється за рідкісними винятками, це через помилку кодування. +Отже, оскільки ми не можемо технічно нічого з цим зробити, у реальних проектах немає жодних математичних дій з об’єктами. Навіть коли в рідкісних винятках це трапляється, то це через помилку в коді. У цьому розділі ми розглянемо те, як об’єкти перетворюється на примітиви і як налаштувати це. У нас є дві цілі: -1. Це дозволить нам зрозуміти, що відбувається у випадку помилок коду, коли така операція відбулася випадково. +1. Це дозволить нам зрозуміти, що відбувається у випадку помилок в коді, коли така операція відбулася випадково. 2. Є винятки, де такі операції можливі та доцільні. Наприклад, віднімання або порівняння дати (`Date` об’єкти). Ми будемо зустрічатися з ними пізніше. ## Правила перетворення -У розділі ми розглянули правила числових, рядкових та логічних перетворень примітивів. Але ми залишили прогалину для об'єктів. Тепер, коли ми знаємо про методи і символи, стає можливим заповнити її. +У розділі ми розглянули правила числових, рядкових та логічних перетворень примітивів. Але ми пропустили перетворення об'єктів. Тепер, коли ми знаємо про методи і символи, стає можливим це зробити. 1. Немає ніякого перетворення в тип Boolean. Всі об'єкти є істинними (true) в булевому контексті, ось так просто. Існують лише числові та рядкові перетворення. -2. Числове перетворення відбувається, коли ми віднімаємо об’єкти або застосовуємо математичні функції. Наприклад, `Date` об’єкти (розглянуті в розділі ) можуть відніматися, і результат `date1 - date2` -- це різниця у часі між двома датами. -3. Що стосується перетворення рядків -- це зазвичай відбувається, коли ми виводимо об’єкт, наприклад `alert(obj)` і в подібних контекстах. +2. Числове перетворення відбувається коли ми віднімаємо об’єкти або застосовуємо математичні функції. Наприклад, `Date` об’єкти (розглянуті в розділі ) можуть відніматися, і результат `date1 - date2` -- це різниця у часі між двома датами. +3. Що стосується перетворення рядків -- це зазвичай відбувається коли ми виводимо об’єкт (наприклад `alert(obj)` та в подібних ситуаціях). Ми можемо реалізувати перетворення рядків і чисел самостійно, використовуючи спеціальні методи об’єкта. @@ -36,10 +36,10 @@ JavaScript не дозволяє налаштувати те, як працюю Як JavaScript вирішує, яке перетворення застосувати? -Є три варіанти перетворення типів, що відбуваються в різних ситуаціях. Вони називаються "підказками" ("hints"), і описані в [специфікації](https://tc39.github.io/ecma262/#sec-toprimitive): +Є три варіанти перетворення типів, що відбуваються в різних ситуаціях. Вони називаються "підказками" (англ. hints), і описані в [специфікації](https://tc39.github.io/ecma262/#sec-toprimitive): `"string"` -: Перетворення об’єкта в рядок відбувається коли ми виконуємо операцію над об'єктом, який очікує рядок. Наприклад, `alert`: +: Для перетворення об’єкта в рядок. Тоді, коли ми виконуємо над об'єктом операцію, яка очікує рядок. Наприклад, `alert`: ```js // вивід @@ -50,7 +50,7 @@ JavaScript не дозволяє налаштувати те, як працюю ``` `"number"` -: Перетворення об’єкта в число, коли ми робимо математичні операції: +: Для перетворення об’єкта в число. Тоді, коли ми робимо математичні операції: ```js // явне перетворення @@ -64,14 +64,14 @@ JavaScript не дозволяє налаштувати те, як працюю let greater = user1 > user2; ``` - Більшість вбудованих математичних функцій також включають таке перетворення. + Більшість вбудованих математичних функцій також включають і такі перетворення. `"default"` -: Виникає в рідкісних випадках, коли оператор "не впевнений", який тип очікується. +: Трапляється в рідкісних випадках, коли оператор "не впевнений", який тип очікувати. - Наприклад, бінарний плюс `+` може працювати як з рядками (об’єднує їх), так і з цифрами (додає їх), тому обидва випадки -- рядки та цифри -- будуть працювати. Отже, якщо бінарний плюс отримує об’єкт як аргумент, він використовує підказку `"default"` для його перетворення. + Наприклад, бінарний плюс `+` може працювати як з рядками (об’єднує їх), так і з цифрами (додає їх), тому обидва випадки -- і рядки, і цифри -- будуть працювати. Отже, якщо бінарний плюс отримує об’єкт як аргумент, він використовує підказку `"default"` для його перетворення. - Також, якщо об’єкт порівнюється за допомогою (`==`) з рядком, числом чи символом, також незрозуміло, яке перетворення слід виконати, тому використовується підказка `"default"`. + Також, якщо об’єкт порівнюється за допомогою (`==`) з рядком, числом або символом, то також незрозуміло, яке перетворення слід виконати, тому використовується підказка `"default"`. ```js // бінарний плюс використовує підказку "default" @@ -81,37 +81,37 @@ JavaScript не дозволяє налаштувати те, як працюю if (user == 1) { ... }; ``` - Оператори порівняння більше та менше, такі як `<` `>`, також можуть працювати як з рядками, так і з числами. Проте, вони з історичних причин використовують підказку `"number"` , а не `"default"`. + Оператори порівняння більше та менше, такі як `<` `>`, також можуть працювати як з рядками, так і з числами. Проте, вони з історичних причин використовують підказку `"number"` , а не підказку `"default"`. Але на практиці все трохи простіше. -Всі вбудовані об’єкти, крім одного випадку (об’єкт `Date`, ми дізнаємося пізніше) реалізовують перетворення `"default"` так само як `"number"`. І нам, мабуть, слід робити так само. +Всі вбудовані об’єкти, за винятком лише об’єкту `Date` (про який ми дізнаємося пізніше), реалізовують перетворення з підказкою `"default"` так само як з підказкою `"number"`. І нам, мабуть, слід робити так само. -Проте важливо знати про всі три підказки, незабаром ми побачимо, чому. +Проте важливо знати про всі три підказки і незабаром ми побачимо чому. -** Щоб зробити перетворення, JavaScript намагається знайти та викликати три методи об’єкта: ** +**Щоб зробити перетворення, JavaScript намагається знайти та викликати три методи об’єкта:** -1. Викликати `obj[Symbol.toPrimitive](hint)` -- метод з символьним ключем `Symbol.toPrimitive` (системний символ), якщо такий метод існує, -2. Інакше, якщо підказка - це `"string"` - - спробує викликати `obj.toString()` або `obj.valueOf()` -- залежно від того, що існує. -3. Інакше, якщо підказка має значення - `"число"` або `"default"` - - спробує викликати `obj.valueOf()` або `obj.toString()` -- залежно від того, що існує. +1. Викликати метод `obj[Symbol.toPrimitive](hint)` (це такий метод з символьним ключем `Symbol.toPrimitive` (системний символ)), якщо в цього об'єкта такий метод існує, +2. Інакше, якщо підказка має значення `"string"` + - спробує викликати `obj.toString()` або `obj.valueOf()` -- залежно від того, який з цих методів наявний для конкретного об'єкта. +3. Або, якщо підказка має значення `"number"` або `"default"` + - спробує викликати `obj.valueOf()` або `obj.toString()` -- залежно від того, який з цих методів наявний для конкретного об'єкта. ## Symbol.toPrimitive -Почнемо з першого методу. Є вбудований символ під назвою `Symbol.toPrimitive`, який слід використовувати для назви методу перетворення, як, наприклад: +Почнемо з першого методу. Є вбудований символ під назвою `Symbol.toPrimitive`, який слід використовувати щоб назвати метод перетворення, як, наприклад: ```js obj[Symbol.toPrimitive] = function(hint) { // тут йде код, щоб перетворити цей об’єкт в примітив // він повинен повернути примітивне значення - // hint = один з "string", "number", "default" + // в hint надходить або "string", або "number", або "default" }; ``` -Якщо метод `symbol.toPrimitive` існує, він використовується для всіх підказок, і не потрібно більше методів. +Якщо метод `symbol.toPrimitive` в конкретного об'єкта існує, він буде використовуватись для всіх підказок, і ніякі інші методи не потрібні. -Наприклад, тут об’єкт `user` реалізує його: +Наприклад, тут об’єкт `user` імплементує цей метод: ```js run let user = { @@ -125,25 +125,25 @@ let user = { }; // демонстрація перетворення: -alert(user); // hint: string -> {name: "Іван"} -alert(+user); // hint: number -> 1000 -alert(user + 500); // hint: default -> 1500 +alert(user); // виведе 'hint: string' і поверне '{name: "Іван"}' +alert(+user); // виведе 'hint: number' і поверне 1000 +alert(user + 500); // виведе 'hint: default' і поверне 1500 ``` -Як ми бачимо з коду, `user` стає само описаним рядком або грошовою сумою залежно від перетворення. Єдиний метод `[Symbol.toPrimitive]` об’єкту `user` обробляє всі випадки перетворення. +Як ми бачимо з коду, `user` стає самоописуючим рядком або грошовою сумою в залежності від способу перетворення. Один метод `[Symbol.toPrimitive]` об’єкту `user` обробляє всі випадки перетворення. ## toString/valueOf -Якщо немає `Symbol.toPrimitive` тоді JavaScript намагається знайти методи `toString` і `valueOf`: +Якщо немає `Symbol.toPrimitive` тоді JavaScript намагається знайти хоча б якийсь з методів `toString` і `valueOf`: -- Підказка для `"string"`: виклик методу `toString`, і якщо цей метод не існує або якщо він повертає об'єкт замість примітивного значення, тоді викликати `valueOf` (таким чином `toString` має пріоритет при перетворенні в рядок). -- Для інших підказок: `valueOf`, і якщо це не існує або якщо він повертає об'єкт замість примітивного значення, тоді викликати `toString` (таким чином `valueOf` має пріоритет для математичних дій). +- Якщо підказка має значення `"string"`: JavaScript спершу спробує виклика метод `toString`, і якщо в цього об'єкта цей метод не існує або якщо він повертає об'єкт замість примітивного значення, тоді викличе `valueOf` (таким чином, при перетворенні об'єкта в рядок пріоритет має `toString`). +- Якщо підказка має значення `"number"`/`"default"`, JavaScript спершу спробує викликати `valueOf`, і якщо цей метод в цього об'єкта не існує або якщо він повертає об'єкт замість примітивного значення, тоді викличе `toString` (таким чином, для математичних дій пріоритет має `valueOf`). -Методи `toString` і `valueOf` походять з давніх часів. Вони не є символами (багато часу назад символи не існували), а скоріше є "звичайними" методами, що названі за допомогою рядків. Вони надають альтернативний «старомодний» спосіб реалізації перетворення. +Методи `toString` і `valueOf` походять з стародавніх часів. Вони не є символами (багато років назад символи не існували), а скоріше є "звичними" методами, що названі за допомогою рядків. Вони надають альтернативний «старомодний» спосіб реалізації перетворення. -Ці методи повинні повертати примітивне значення. Якщо `toString` чи `valueOf` повертає об’єкт, то він ігнорується (так само, якби цього методу не існувало). +Ці методи повинні повертати примітивне значення. Якщо `toString` чи `valueOf` повертає об’єкт, то цей метод ігнорується (так само, якби цього методу не існувало). -За замовчуванням, звичайний об’єкт має наступні методи `toString` та `valueOf`: +За замовчуванням, в звичайного об'єкта є методи `toString` та `valueOf`. І працюють вони наступним чином: - Метод `toString` повертає рядок `"[object Object]"`. - Метод `valueOf` повертає сам об’єкт. @@ -159,7 +159,7 @@ alert(user.valueOf() === user); // true Отже, якщо ми спробуємо використовувати об’єкт як рядок, наприклад в `alert` та ін., то за замовчуванням ми побачимо `[object Object]`. -За замовчуванням метод `valueOf` згадується тут лише заради повноти картини, щоб уникнути будь-якої плутанини. Як бачите, він повертає сам об’єкт, і тому ігнорується з історичних причин. Тож ми можемо припустити, що його не існує. +Вбудований метод `valueOf` згадується тут лише заради повноти картини, щоб уникнути будь-якої плутанини. Як бачите, він повертає сам об’єкт. А тому JavaScript його ігнорує. Не питайте мене чому так. Просто так склалось з історичних причин. Власне ми можемо припустити, що його не існує. Давайте реалізуємо ці методи, щоб налаштувати перетворення. @@ -189,7 +189,7 @@ alert(user + 500); // valueOf -> 1500 Як бачимо, поведінка така ж, як і в попередньому прикладі з `Symbol.toPrimitive`. -Часто нам потрібне єдине «універсальне» місце для обробки всіх перетворень примітивів. У цьому випадку ми можемо реалізувати тільки `toString`, ось так: +Часто нам потрібне одне єдине «універсальне» місце для обробки всіх перетворень примітивів. У цьому випадку ми можемо реалізувати тільки `toString`, ось так: ```js run let user = { @@ -204,47 +204,47 @@ alert(user); // toString -> Іван alert(user + 500); // toString -> Іван500 ``` -За відсутності `Symbol.toPrimitive` і `valueOf`, `toString` буде обробляти всі перетворення примітивів. +Якщо відсутній `Symbol.toPrimitive` і `valueOf`, то всі перетворення примітивів буде обробляти `toString`. ### Перетворення може повернути будь-який примітивний тип -Важливо знати про всі методи перетворення примітивів, що вони не обов’язково повертають "підказаний" примітив. +Важливо знати, що методи перетворення примітивів не обов’язково повертають "підказаний" примітив. -Немає контролю, чи повертає `toString` саме рядок, або чи `symbol.toprimitive` метод повертає число для підказки `"number"`. +JavaScript не вимагає від `toString` повернути саме рядок якщо підказка має значення `"string"`. І не вимагає від `Symbol.toPrimitive` повернути число якщо підказка має значення `"number'`. -Єдина обов’язкова річ: ці методи повинні повертати примітивний тип, а не об’єкт. +Єдина вимога до методів перетворення примітивів: ці методи повинні повертати примітивний тип, а не об’єкт. ```smart header="Історичні нотатки" -З історичних причин, якщо `toString` чи `valueOf` повертає об’єкт,це не є помилкою, але таке значення ігнорується (так само, якби цей метод не існував). Це тому, що в давнину в JavaScript не було хорошого концепту "помилка". +З історичних причин, якщо `toString` чи `valueOf` поверне об’єкт, це не призведе до помилки, але таке значення буде проігнороване (так само, якби цей метод не існував). Воно не призведе до помилки лише тому, що в давнину JavaScript не вмів нормально видавати помилки. -На противагу цьому, `Symbol.toPrimitive` суворіший, він *повинен* повернути примітив, інакше буде помилка. +Але, вимоги до `Symbol.toPrimitive` суворіші. Він *мусить* повернути примітив, інакше JavaScript видасть помилку. ``` ## Подальші перетворення -Як ми вже знаємо, багато операторів та функцій виконують перетворення типів, наприклад, множення `*` перетворює операнди в числа. +Як ми вже знаємо, багато операторів та функцій виконують перетворення типів. Наприклад, множення `*` перетворює операнди в числа. Якщо ми передамо об’єкт як аргумент, то відбувається два етапи обчислень: -1. Об’єкт перетворюється на примітив (використовуючи правила, описані вище). -2. Якщо це необхідно для подальших обчислень, то отриманий примітив також перетворюється. +1. Об’єкт буде перетворено на примітив (використовуючи правила, описані вище). +2. Якщо це необхідно для подальших обчислень, то й отриманий примітив також буде перетворено. Наприклад: ```js run let obj = { - // toString обробляє всі перетворення за відсутності інших методів + // За відсутності інших методів, toString обробляє всі перетворення toString() { return "2"; } }; -alert(obj * 2); // 4, об’єкт перетворено на примітив "2", потім множенням отримано число +alert(obj * 2); // 4, бо спершу об’єкт перетворено на примітив "2", а тоді множенням отримано число ``` 1. Множення `obj * 2` спочатку перетворює об’єкт в примітив (це рядок `"2"`). 2. Тоді `"2" * 2` стає `2 * 2` (рядок перетворюється на число). -Бінарний плюс буде об’єднувати рядки в такій же ситуації, оскільки він з радістю приймає рядки: +Бінарний плюс натомість, в точно такій же ситуації буде приймати рядки, оскільки він без проблем приймає рядки: ```js run let obj = { @@ -260,21 +260,21 @@ alert(obj + 2); // 22 ("2" + 2), перетворення до примітив Перетворення об’єкта на примітив викликається автоматично багатьма вбудованими функціями та операторами, які очікують примітив як значення. -Існує 3 типи (підказки) цього перетворення: +Існує 3 типи (підказки) для цього перетворення: - `"string"` (для `alert` та інших операцій, які потребують рядка) - `"number"` (для математичних операцій) -- `"default"` (мало операторів, зазвичай об’єкти реалізують це так само як і `"number"`.) +- `"default"` (для дуже небагатьох операторів; зазвичай об’єкти реалізують це так само як і `"number"`.) Специфікація явно описує, який оператор використовує яку підказку. Алгоритм перетворення наступний: -1. Викликати `obj[Symbol.toPrimitive](hint)`, якщо метод існує, -2. Інакше, якщо підказка -- має значення `"string"` - - спробувати викликати `obj.toString()` або `obj.valueOf()`, залежно від того, що існує. +1. Викликати `obj[Symbol.toPrimitive](hint)`, якщо цей метод в цього об'єкта існує, +2. Інакше, якщо підказка має значення `"string"` + - спробувати викликати `obj.toString()` або `obj.valueOf()`, залежно від того, який з цих методів в цього об'єкта існує. 3. Інакше, якщо підказка -- має значення `"number"` чи `"default"` - - спробувати викликати `obj.valueOf()` або `obj.toString()`, залежно від того, що існує. + - спробувати викликати `obj.valueOf()` або `obj.toString()`, залежно від того, який з цих методів в цього об'єкта існує. -Усі ці методи повинні повертати примітив (якщо визначені). +Усі ці методи мусять повертати примітив (якщо це визначено). На практиці часто достатньо реалізувати лише `obj.toString()` як універсальний метод для перетворення рядків, який повинен повернути "читабельне для людини" представлення об’єкта, для цілей логування або пошуку помилок. From 2cfc33f0dca0efe8c3dafb8a26af99d4c0f59b38 Mon Sep 17 00:00:00 2001 From: Andrii Hrushetskyi Date: Sun, 16 Feb 2025 21:37:07 +0100 Subject: [PATCH 2/2] fix 01-04-09 object-tostring I've read this article again and made it's translation even better and even more clear for understanding. --- .../09-object-toprimitive/article.md | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/1-js/04-object-basics/09-object-toprimitive/article.md b/1-js/04-object-basics/09-object-toprimitive/article.md index df767834d..40288df19 100644 --- a/1-js/04-object-basics/09-object-toprimitive/article.md +++ b/1-js/04-object-basics/09-object-toprimitive/article.md @@ -91,15 +91,15 @@ JavaScript не дозволяє налаштувати те, як працюю **Щоб зробити перетворення, JavaScript намагається знайти та викликати три методи об’єкта:** -1. Викликати метод `obj[Symbol.toPrimitive](hint)` (це такий метод з символьним ключем `Symbol.toPrimitive` (системний символ)), якщо в цього об'єкта такий метод існує, +1. Намагається викликати метод `obj[Symbol.toPrimitive](hint)` (це такий метод з системним символом `Symbol.toPrimitive` в якості символьного ключа), якщо в цього об'єкта такий метод існує, 2. Інакше, якщо підказка має значення `"string"` - - спробує викликати `obj.toString()` або `obj.valueOf()` -- залежно від того, який з цих методів наявний для конкретного об'єкта. + - намагається викликати `obj.toString()` або `obj.valueOf()` -- залежно від того, який з цих методів існує в конкретного об'єкта. 3. Або, якщо підказка має значення `"number"` або `"default"` - - спробує викликати `obj.valueOf()` або `obj.toString()` -- залежно від того, який з цих методів наявний для конкретного об'єкта. + - спробує викликати `obj.valueOf()` або `obj.toString()` -- залежно від того, який з цих методів існує в конкретного об'єкта. ## Symbol.toPrimitive -Почнемо з першого методу. Є вбудований символ під назвою `Symbol.toPrimitive`, який слід використовувати щоб назвати метод перетворення, як, наприклад: +Почнемо з першого методу. Є вбудований символ під назвою `Symbol.toPrimitive`, який слід використовувати в якості ключа методу перетворення, як, наприклад: ```js obj[Symbol.toPrimitive] = function(hint) { @@ -130,20 +130,20 @@ alert(+user); // виведе 'hint: number' і поверне 1000 alert(user + 500); // виведе 'hint: default' і поверне 1500 ``` -Як ми бачимо з коду, `user` стає самоописуючим рядком або грошовою сумою в залежності від способу перетворення. Один метод `[Symbol.toPrimitive]` об’єкту `user` обробляє всі випадки перетворення. +Як ми бачимо з коду, `user` стає самоописуючим рядком або грошовою сумою в залежності від способу перетворення. Один єдиний метод `[Symbol.toPrimitive]` об’єкта `user` обробляє всі випадки перетворення. ## toString/valueOf -Якщо немає `Symbol.toPrimitive` тоді JavaScript намагається знайти хоча б якийсь з методів `toString` і `valueOf`: +Якщо немає `Symbol.toPrimitive` тоді JavaScript намагається знайти методи `toString` і `valueOf`: -- Якщо підказка має значення `"string"`: JavaScript спершу спробує виклика метод `toString`, і якщо в цього об'єкта цей метод не існує або якщо він повертає об'єкт замість примітивного значення, тоді викличе `valueOf` (таким чином, при перетворенні об'єкта в рядок пріоритет має `toString`). -- Якщо підказка має значення `"number"`/`"default"`, JavaScript спершу спробує викликати `valueOf`, і якщо цей метод в цього об'єкта не існує або якщо він повертає об'єкт замість примітивного значення, тоді викличе `toString` (таким чином, для математичних дій пріоритет має `valueOf`). +- Якщо підказка має значення `"string"`: JavaScript спершу спробує викликати метод `toString`, і якщо в цього об'єкта цей метод відсутній або якщо якщо цей метод повертає об'єкт замість примітивного значення, тоді JavaScript викличе `valueOf` (таким чином, при перетворенні об'єкта в рядок пріоритет має `toString`). +- Якщо підказка має значення `"number"`/`"default"`, JavaScript спершу спробує викликати `valueOf`, і якщо цей метод відсутній або якщо якщо цей метод повертає об'єкт замість примітивного значення, тоді JavaScript викличе `toString` (таким чином, для математичних дій пріоритет має `valueOf`). -Методи `toString` і `valueOf` походять з стародавніх часів. Вони не є символами (багато років назад символи не існували), а скоріше є "звичними" методами, що названі за допомогою рядків. Вони надають альтернативний «старомодний» спосіб реалізації перетворення. +Методи `toString` і `valueOf` походять з стародавніх часів. Вони не є символами (багато років назад символів в JavaScript не існувало), а скоріше є "звичними" методами, що названі за допомогою рядків. Вони надають альтернативний «старомодний» спосіб реалізації перетворення. Ці методи повинні повертати примітивне значення. Якщо `toString` чи `valueOf` повертає об’єкт, то цей метод ігнорується (так само, якби цього методу не існувало). -За замовчуванням, в звичайного об'єкта є методи `toString` та `valueOf`. І працюють вони наступним чином: +В звичайного об'єкта методи `toString` та `valueOf` присутні за замовчуванням. І за замовчуванням вони вони працюють наступним чином: - Метод `toString` повертає рядок `"[object Object]"`. - Метод `valueOf` повертає сам об’єкт. @@ -159,11 +159,11 @@ alert(user.valueOf() === user); // true Отже, якщо ми спробуємо використовувати об’єкт як рядок, наприклад в `alert` та ін., то за замовчуванням ми побачимо `[object Object]`. -Вбудований метод `valueOf` згадується тут лише заради повноти картини, щоб уникнути будь-якої плутанини. Як бачите, він повертає сам об’єкт. А тому JavaScript його ігнорує. Не питайте мене чому так. Просто так склалось з історичних причин. Власне ми можемо припустити, що його не існує. +Вбудований метод `valueOf` згадується тут лише заради повноти картини, щоб уникнути непорозумінь. Бо JavaScript цей метод ігнорує. Ігнорує, бо як бачите, цей метод повертає сам об’єкт. Не питайте мене чому так. Просто так склалось з історичних причин. Власне ми можемо уявити ніби об'єкта `valueOf` не існує. -Давайте реалізуємо ці методи, щоб налаштувати перетворення. +Давайте самостійно реалізуємо ці методи, щоб налаштувати перетворення. -Наприклад, тут `user` робить те ж саме, що й вище, використовуючи комбінацію `toString` і `valueOf` замість `Symbol.toPrimitive`: +Наприклад, тут `user` при перетворенні стає тим самим, що й в прикладі вище, але цього разу використовуючи комбінацію `toString` і `valueOf` замість `Symbol.toPrimitive`: ```js run let user = { @@ -208,14 +208,14 @@ alert(user + 500); // toString -> Іван500 ### Перетворення може повернути будь-який примітивний тип -Важливо знати, що методи перетворення примітивів не обов’язково повертають "підказаний" примітив. +Важливо знати, що методи перетворення примітивів не обов’язково повертають примітив "підказаного" типу. JavaScript не вимагає від `toString` повернути саме рядок якщо підказка має значення `"string"`. І не вимагає від `Symbol.toPrimitive` повернути число якщо підказка має значення `"number'`. -Єдина вимога до методів перетворення примітивів: ці методи повинні повертати примітивний тип, а не об’єкт. +Єдина вимога до методів перетворення примітивів: ці методи повинні повертати саме примітивний тип, а не об’єкт. ```smart header="Історичні нотатки" -З історичних причин, якщо `toString` чи `valueOf` поверне об’єкт, це не призведе до помилки, але таке значення буде проігнороване (так само, якби цей метод не існував). Воно не призведе до помилки лише тому, що в давнину JavaScript не вмів нормально видавати помилки. +З історичних причин, якщо `toString` чи `valueOf` поверне об’єкт, це не призведе до помилки. Таке значення буде просто проігнороване (так само, якби цей метод не існував). Воно не призведе до помилки лише тому, що в давнину JavaScript не вмів нормально видавати помилки. Але, вимоги до `Symbol.toPrimitive` суворіші. Він *мусить* повернути примітив, інакше JavaScript видасть помилку. ``` @@ -241,10 +241,10 @@ let obj = { alert(obj * 2); // 4, бо спершу об’єкт перетворено на примітив "2", а тоді множенням отримано число ``` -1. Множення `obj * 2` спочатку перетворює об’єкт в примітив (це рядок `"2"`). -2. Тоді `"2" * 2` стає `2 * 2` (рядок перетворюється на число). +1. Множення `obj * 2` спочатку перетворює об’єкт в примітив (вийде рядок `"2"`). +2. Тоді `"2" * 2` стане `2 * 2` (рядок перетворюється на число). -Бінарний плюс натомість, в точно такій же ситуації буде приймати рядки, оскільки він без проблем приймає рядки: +Бінарний плюс натомість, в точно такій же ситуації буде з радістю приймати рядки, оскільки він вміє працювати не лише з числами, а й з рядками: ```js run let obj = { @@ -265,16 +265,16 @@ alert(obj + 2); // 22 ("2" + 2), перетворення до примітив - `"number"` (для математичних операцій) - `"default"` (для дуже небагатьох операторів; зазвичай об’єкти реалізують це так само як і `"number"`.) -Специфікація явно описує, який оператор використовує яку підказку. +Специфікація явно описує який оператор використовує яку підказку. Алгоритм перетворення наступний: -1. Викликати `obj[Symbol.toPrimitive](hint)`, якщо цей метод в цього об'єкта існує, +1. Викликати `obj[Symbol.toPrimitive](hint)` (якщо цей метод в цього об'єкта існує), 2. Інакше, якщо підказка має значення `"string"` - спробувати викликати `obj.toString()` або `obj.valueOf()`, залежно від того, який з цих методів в цього об'єкта існує. -3. Інакше, якщо підказка -- має значення `"number"` чи `"default"` +3. Інакше, якщо підказка має значення `"number"` чи `"default"` - спробувати викликати `obj.valueOf()` або `obj.toString()`, залежно від того, який з цих методів в цього об'єкта існує. -Усі ці методи мусять повертати примітив (якщо це визначено). +Виклик усіх цих методів повинен повертати примітив (якщо ці методи визначені). -На практиці часто достатньо реалізувати лише `obj.toString()` як універсальний метод для перетворення рядків, який повинен повернути "читабельне для людини" представлення об’єкта, для цілей логування або пошуку помилок. +На практиці часто достатньо реалізувати лише `obj.toString()` як універсальний метод для перетворення рядків, який повинен повернути "читабельне для людини" представлення об’єкта для цілей логування або пошуку помилок.