Skip to content

Commit de65ae8

Browse files
committed
fixed typos and simplified explanation
**In chapter 01-06-09 call apply decorators** Some of sentences were correct, but they were "unnatural" in Ukrainian and make understanding more difficult.
1 parent a62746d commit de65ae8

1 file changed

Lines changed: 27 additions & 27 deletions

File tree

  • 1-js/06-advanced-functions/09-call-apply-decorators

1-js/06-advanced-functions/09-call-apply-decorators/article.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ JavaScript дає виняткову гнучкість при роботі з
66

77
Скажімо, у нас є функція `slow(x)`, яка виконує ресурсоємкі операції, але її результати стабільні. Іншими словами, для того ж `x` вона завжди повертає той же результат.
88

9-
Якщо функція часто викликається, ми можемо кешувати (запам’ятати) її результати, щоб не витрачати час на перерахування.
9+
Якщо функція часто викликається, ми можемо кешувати (запам’ятати) її результати, щоб не витрачати час на повторне обчислення.
1010

1111
Але замість того, щоб додати цю функціональність в `slow()` ми створимо функцію-обгортку, що додає кешування. Як ми побачимо, існує багато переваг такого підходу.
1212

@@ -23,7 +23,7 @@ function cachingDecorator(func) {
2323
let cache = new Map();
2424

2525
return function(x) {
26-
if (cache.has(x)) { // якщо такий ключ є в кеш
26+
if (cache.has(x)) { // якщо такий ключ є в кеші
2727
return cache.get(x); // прочитайти результат з нього
2828
}
2929

@@ -63,7 +63,7 @@ alert( "Again: " + slow(2) ); // slow(2) result returned from cache
6363

6464
## Використання "func.call" для контексту
6565

66-
Кешуючий декоратор, згаданий вище, не підходить для роботи з методами об’єкта.
66+
Написаний вище кешуючий декоратор не підходить для роботи з методами об’єкта.
6767

6868
Наприклад, у коді нижче `worker.slow()` перестане працювати після використання декоратора:
6969

@@ -138,7 +138,7 @@ func.call(obj, 1, 2, 3)
138138

139139
Обидва вони викликаюсь `func` з аргументами `1`, `2` і `3`. Єдина відмінність полягає в тому, що `func.call` також встановлює `this` рівним `obj`.
140140

141-
Як приклад, у коді нижче ми викликаємо `sayHi` в контексті різних об’єктів: `sayHi.call(user)` викликає `sayHi`, передаючи `this=user`, а на наступних рядках встановлюється `this=admin`:
141+
Як приклад, у коді нижче ми викликаємо `sayHi`, передаючи їй в якості контексту (в якості `this`) різні об'єкти: `sayHi.call(user)` викликає `sayHi`, передаючи `this=user`, а на наступних рядках встановлюється `this=admin`:
142142

143143
```js run
144144
function sayHi() {
@@ -205,7 +205,7 @@ alert( worker.slow(2) ); // працює, не викликаючи оригін
205205

206206
Щоб все було зрозуміло, давайте подивимося більш глибоко, як `this` передається:
207207

208-
1. Після декорування `worker.slow` стає функцією обгортки `function (x) { ... }`.
208+
1. Після декорування в значення `worker.slow` було присвоєно функцію декоратор `function (x) { ... }`.
209209
2. Отже, коли `worker.slow(2)` виконується, обгортка отримує `2` в якості аргумента і `this=worker` (це об’єкт перед крапкою).
210210
3. Всередині обгортки, якщо результат ще не кешований, `func.call(this, x)` передає поточний `this` (`=worker`) та поточний аргумент (`=2`) до оригінального методу.
211211

@@ -226,15 +226,15 @@ let worker = {
226226
worker.slow = cachingDecorator(worker.slow);
227227
```
228228

229-
Раніше, для одного аргументу `x`, ми могли просто `cache.set(x, result)`, щоб зберегти результат та `cache.get(x)`, щоб отримати його. Але тепер нам потрібно пам’ятати результат для *комбінації аргументів* `(min,max)`. Вбудований `Map` приймає лише одне значення як ключ.
229+
Раніше, для одного аргументу `x`, ми могли написати просто `cache.set(x, result)`, щоб зберегти результат та `cache.get(x)`, щоб отримати його. Але тепер нам потрібно пам’ятати результат для *комбінації аргументів* `(min,max)`. Вбудований `Map` приймає лише одне значення як ключ.
230230

231231
Є багато можливих рішень:
232232

233-
1. Впровадити нову (або скористайтеся сторонньою) map-подібну структуру даних, яка більш універсальна і дозволяє використовувати декілька ключів.
233+
1. Впровадити нову (або взяти готову сторонню) map-подібну структуру даних, яка більш універсальна і дозволяє використовувати декілька ключів.
234234
2. Використати вкладені коллекції: `cache.set(min)` буде `Map`, що зберігає пару `(max, result)`. Таким чином, ми можемо отримати `result` як `cache.get(min).get(max)`.
235-
3. З’єднати два значення в одне. У нашому конкретному випадку ми можемо просто використовувати рядок `"min,max"` як ключ `Map`. Для гнучкості ми можемо забезпечити *функція хешування* для декоратора, що знає, як зробити одне значення з багатьох.
235+
3. З’єднати два значення в одне. У нашому конкретному випадку ми можемо просто використовувати рядок `"min,max"` як ключ `Map`. Для гнучкості ми можемо забезпечити *функцію хешування* для декоратора, що знає, як зробити одне значення з багатьох.
236236

237-
Для багатьох практичних застосунків, 3-й варіант досить хороший, тому ми будемо дотримуватися його.
237+
На практиці частіше всього використовують 3-й варіант, тому ми будемо дотримуватися його.
238238

239239
Також ми повинні передати не просто `x`, але всі аргументи в `func.call`. Давайте пригадаємо, що в `function()` ми можемо отримати псевдо-масив її аргументів, як `arguments`, тому `func.call(this, x)` слід замінити на `func.call(this, ...arguments)`.
240240

@@ -281,8 +281,8 @@ alert( "Знову " + worker.slow(3, 5) ); // те ж саме значення
281281

282282
Є дві зміни:
283283

284-
- В рядку `(*)` викликається `hash`, щоб створити одну ключ з `arguments`. Тут ми використовуємо просту функцію "приєднання", яка перетворює аргументи `(3, 5)` у ключ `"3,5"`. Більш складні випадки можуть потребувати інших функцій хешування.
285-
- Потім `(**)` використовує `func.call(this, ...arguments)`, щоб передати як контекст, так і всі аргументи (а не тільки перший) обгортки до оригінальної функції.
284+
- В рядку `(*)` викликається `hash`, щоб створити один ключ з `arguments`. Тут ми використовуємо просту функцію "приєднання", яка перетворює аргументи `(3, 5)` у ключ `"3,5"`. Більш складні випадки можуть потребувати інших функцій хешування.
285+
- Потім `(**)` використовує `func.call(this, ...arguments)`, щоб передати як контекст, так і всі аргументи (а не тільки перший) з обгортки до оригінальної функції.
286286

287287
## func.apply
288288

@@ -305,16 +305,16 @@ func.call(context, ...args);
305305
func.apply(context, args);
306306
```
307307

308-
Вони виконують той самий виклик `func` з даним контекстом та аргументами.
308+
Вони виконують той самий виклик `func` з вручну вказаним їм контекстом (`this`) та аргументами.
309309

310310
Є тільки тонка різниця щодо `args`:
311311

312-
- Оператор розширення `...` дозволяє передати *ітерований* `args` як список до `call`.
312+
- Оператор розширення `...` дозволяє передати *ітеровуваний* `args` у вигляді окремих елементів до `call`.
313313
- `apply` приймає лише *псевдо-масив* `args`.
314314

315-
... і для обєктів, які є як ітерованими, так і псевдо-масивами, а так само як і справжніми масивами, ми можемо використовувати будь-який з цих методів, але `apply`, мабуть, буде швидше, тому що більшість рушіїв JavaScript внутрішньо оптимізують його краще.
315+
...А для об'єктів, які є одночасно і ітеровуваними, і псевдомасивами чи й справжніми масивами, ми можемо використовувати будь-який з цих методів. Але `apply`, мабуть, буде працювати швидше, бо більшість рушіїв JavaScript внутрішньо оптимізовують його краще.
316316

317-
Передача всіх аргументів разом з контекстом до іншої функції називається *переадресація виклику*.
317+
Передача всіх аргументів разом з контекстом до іншої функції називається *переадресація виклику* (call forwarding).
318318

319319
Це найпростіша її форма:
320320

@@ -336,24 +336,24 @@ function hash(args) {
336336
}
337337
```
338338

339-
Зараз вона працює лише на двох аргументах. Було б краще, якби вона могла зкріпити будь-яку кількість `args`.
339+
Зараз вона працює лише для двох аргументів. Було б краще, якби вона могла зклеїти будь-яку кількість `args`.
340340

341-
Звичайним рішенням буде використати [arr.join](mdn:js/Array/join) метод:
341+
Перше, що приходить в голову - це використати метод [arr.join](mdn:js/Array/join):
342342

343343
```js
344344
function hash(args) {
345345
return args.join();
346346
}
347347
```
348348

349-
...На жаль, це не буде працювати. Тому що ми викликаємо `hash(arguments)`, а об’єкт `arguments` є як ітерованим, так і псевдо-масивом, але не справжнім масивом.
349+
...На жаль, це не буде працювати. Ми викликаємо `hash(arguments)`, а об’єкт `arguments` є одночасно як ітеровуваним, так і псевдо-масивом, але не справжнім масивом.
350350

351351
Отже, виклик `join` на цьому об’єкті буде призводити до помилки, що ми бачимо нижче:
352352

353353
```js run
354354
function hash() {
355355
*!*
356-
alert( arguments.join() ); // Помилка: arguments.join не є функцією
356+
alert( arguments.join() ); // TypeError: arguments.join is not a function
357357
*/!*
358358
}
359359

@@ -374,7 +374,7 @@ hash(1, 2);
374374

375375
Трюк називається *запозичення методу*.
376376

377-
Ми беремо (запозичуємо) метод приєднання від звичайного масиву (`[].join`) і використовуємо `[].join.call` щоб запустити його в контексті `arguments`.
377+
Ми беремо (запозичуємо) метод приєднання від звичайного масиву (`[].join`) і використовуємо `[].join.call` щоб запустити його з `arguments` в якості його `this`.
378378

379379
Чому це працює?
380380

@@ -394,24 +394,24 @@ hash(1, 2);
394394

395395
## Декоратори та функціональні властивості
396396

397-
Як правило, можна безпечно замінити функцію або метод декоратором, за винятком однієї дрібниці. Якщо оригінальна функція мала властивості в собі, як наприклад `func.calledCount` або щось інше, то декорований об’єкт не буде надавати доступ до них. Тому що це обгортка. Тому потрібно бути обережним, якщо використовує її.
397+
Як правило, можна безпечно замінити функцію або метод декоратором, за винятком однієї дрібниці. Якщо оригінальна функція мала властивості в собі, як наприклад `func.calledCount` або щось інше, то декорований об’єкт не буде надавати доступ до них. Бо це обгортка. Тому потрібно бути обережним, якщо використовуєте її.
398398

399-
Наприклад, у прикладі вище, якщо `slow` функція мала будь-які властивості в собі, то `cachingDecorator(slow)` -- це обгортка без них.
399+
Наприклад, у прикладі вище, якщо `slow` функція мала б будь-які властивості в собі, то `cachingDecorator(slow)` повернув би обгортку без них.
400400

401-
Деякі декоратори можуть забезпечити свої власні властивості.Наприклад, декоратор може підрахувати, скільки разів функція була викликана, і скільки часу це зайняло, і виставляти цю інформацію за допомогою властивостей обгортки.
401+
Деякі декоратори можуть забезпечити свої власні властивості. Наприклад, декоратор може підрахувати, скільки разів функція була викликана, і скільки часу це зайняло, і виставляти цю інформацію за допомогою властивостей обгортки.
402402

403403
Існує спосіб створити декоратори, які зберігають доступ до властивостей функцій, але це вимагає використання спеціального об’єкту `Proxy`, щоб обернути функцію. Ми обговоримо це пізніше у статті <info:proxy#proxy-apply>.
404404

405405
## Підсумки
406406

407-
*Декоратор* -- це обгортка навколо функції, яка змінює її поведінку. Основна робота все ще виконується за допомогою функції.
407+
*Декоратор* -- це обгортка навколо функції, яка повторює її поведінку. Основна робота все ще виконується за допомогою функції.
408408

409409
Декоратори можна розглядати як "особливості" або "аспекти", які можна додати до функції. Ми можемо додати один або додати багато декораторів. І все це, не змінюючи коду оригінальної функції!
410410

411411
Для реалізації `cachingDecorator`, ми вивчали методи:
412412

413-
- [func.call(context, arg1, arg2...)](mdn:js/Function/call) -- викликає `func` з заданим контекстом та аргументами.
414-
- [func.apply(context, args)](mdn:js/Function/apply) -- викликає `func` передаючи `context` як `this` та псевдо-масив `args` як список аргументів.
413+
- [func.call(context, arg1, arg2...)](mdn:js/Function/call) -- викликає `func` з вручним указанням контексту та з списком аргументів.
414+
- [func.apply(context, args)](mdn:js/Function/apply) -- викликає `func` з вручним указанням контексту та псевдо-масив (або й звичайний масив) `args` як список аргументів.
415415

416416
Зазвичай *переадресація викликів* виконується завдяки `apply`:
417417

@@ -421,6 +421,6 @@ let wrapper = function() {
421421
};
422422
```
423423

424-
Ми також бачили приклад *запозичення методу*, коли ми беремо метод з об’єкта та `call` його в контексті іншого об’єкта.Досить поширено брати методи масиву та застосувати їх до `arguments`. Альтернативою є використання об’єкта, який є справжнім масивом, за допомогою rest оператору.
424+
Ми також бачили приклад *запозичення методу*, коли ми беремо метод з об’єкта та викликаємо (`call`), встановлюючи йому в якості this інший об'єкт. Досить поширено брати методи масиву та застосувати до них `arguments`. Альтернативою є використання об’єкта, який є справжнім масивом, за допомогою rest оператору.
425425

426426
На практиці є багато декораторів для різних задач. Перевірте, наскільки добре ви засвоїли їх, вирішивши завдання цієї глави.

0 commit comments

Comments
 (0)