From 4f6e7e456f401721869ae8d2b83971d0d55666f1 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 25 Sep 2021 21:56:20 +0300 Subject: [PATCH 1/8] Function binding --- .../2-write-to-object-after-bind/solution.md | 6 +- .../2-write-to-object-after-bind/task.md | 6 +- .../10-bind/3-second-bind/solution.md | 10 +- .../10-bind/3-second-bind/task.md | 10 +- .../solution.md | 4 +- .../4-function-property-after-bind/task.md | 10 +- .../10-bind/5-question-use-bind/solution.md | 22 +- .../10-bind/5-question-use-bind/task.md | 18 +- .../10-bind/6-ask-partial/solution.md | 6 +- .../10-bind/6-ask-partial/task.md | 18 +- 1-js/06-advanced-functions/10-bind/article.md | 200 +++++++++--------- 11 files changed, 155 insertions(+), 155 deletions(-) diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md index 737a14481..b349d5314 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md @@ -1,4 +1,4 @@ -The answer: `null`. +Відповідь: `null`. ```js run @@ -13,6 +13,6 @@ let user = { user.g(); ``` -The context of a bound function is hard-fixed. There's just no way to further change it. +Контекст прив'язаної функції жорстко-фіксований. Немає способу змінити це в подальшому. -So even while we run `user.g()`, the original function is called with `this=null`. +Так чином в той час як ми запускаємо `user.g()`, функція `f` викликається з `this=null`. diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md index 6d7e1fb24..1fd4942db 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md @@ -1,10 +1,10 @@ -importance: 5 +важливість: 5 --- -# Bound function as a method +# Прив'язана функція як метод -What will be the output? +Що виведе функція? ```js function f() { diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md index 97e1c2809..dacb90668 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md @@ -1,15 +1,15 @@ -The answer: **John**. +Відповідь: **Іван**. ```js run no-beautify function f() { alert(this.name); } -f = f.bind( {name: "John"} ).bind( {name: "Pete"} ); +f = f.bind( {name: "Іван"} ).bind( {name: "Христя"} ); -f(); // John +f(); // Іван ``` -The exotic [bound function](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) object returned by `f.bind(...)` remembers the context (and arguments if provided) only at creation time. +Екзотичний об'єкт [прив'язаної функції](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) повертається від `f.bind(...)`, що запам'ятовує контекст (та аргументи, якщо передані) тільки під час створення. -A function cannot be re-bound. +Функція не може бути переприв'язана. diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md index 5daf053c6..06e6d2f5d 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md @@ -1,19 +1,19 @@ -importance: 5 +важливість: 5 --- -# Second bind +# Друга прив'язка -Can we change `this` by additional binding? +Чи можемо ми змінити `this` за допомогою додаткового прив'язування? -What will be the output? +Який результат буде виведено? ```js no-beautify function f() { alert(this.name); } -f = f.bind( {name: "John"} ).bind( {name: "Ann" } ); +f = f.bind( {name: "Іван"} ).bind( {name: "Христя" } ); f(); ``` diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md index 181555d95..5aadf02e9 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md @@ -1,4 +1,4 @@ -The answer: `undefined`. +Відповідь: `undefined`. -The result of `bind` is another object. It does not have the `test` property. +Результатом `bind` є інший об'єкт. Він не містить властивість `test`. diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md index d6cfb44bf..d81ac049f 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md @@ -1,10 +1,10 @@ -importance: 5 +важливість: 5 --- -# Function property after bind +# Властивість функції після прив'язки -There's a value in the property of a function. Will it change after `bind`? Why, or why not? +Функції присвоєна властивість зі значенням. Чи зміниться вона після `bind`? Чому? ```js run function sayHi() { @@ -14,10 +14,10 @@ sayHi.test = 5; *!* let bound = sayHi.bind({ - name: "John" + name: "Іван" }); -alert( bound.test ); // what will be the output? why? +alert( bound.test ); // що виведе функція? Чому? */!* ``` diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md index 403107ca6..b0f33e437 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md @@ -1,26 +1,26 @@ -The error occurs because `ask` gets functions `loginOk/loginFail` without the object. +Помилка виникає тому що `askPassword` отримує функції `loginOk/loginFail` без об'єкту. -When it calls them, they naturally assume `this=undefined`. +Коли вона викликає їх, їх контекст втрачено `this=undefined`. -Let's `bind` the context: +Спробуємо використати `bind`, щоб прив'язати контекст: ```js run function askPassword(ok, fail) { - let password = prompt("Password?", ''); + let password = prompt("Пароль?", ''); if (password == "rockstar") ok(); else fail(); } let user = { - name: 'John', + name: 'Іван', loginOk() { - alert(`${this.name} logged in`); + alert(`${this.name} увійшов`); }, loginFail() { - alert(`${this.name} failed to log in`); + alert(`${this.name} виконав невдалу спробу входу`); }, }; @@ -30,14 +30,14 @@ askPassword(user.loginOk.bind(user), user.loginFail.bind(user)); */!* ``` -Now it works. +Тепер це працює. -An alternative solution could be: +Альтернативне рішення могло б бути: ```js //... askPassword(() => user.loginOk(), () => user.loginFail()); ``` -Usually that also works and looks good. +Зазвичай це також працює та чудово виглядає. -It's a bit less reliable though in more complex situations where `user` variable might change *after* `askPassword` is called, but *before* the visitor answers and calls `() => user.loginOk()`. +Це менш найдіно, так як в більш складних ситуаціях змінна `user` може змінитися *після* виклику `askPassword`, але *перед* викликом `() => user.loginOk()`. diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md index fe6a9b4eb..2945bc806 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md @@ -1,31 +1,31 @@ -importance: 5 +важливість: 5 --- -# Fix a function that loses "this" +# Виправте функцію, яка втратила 'this' -The call to `askPassword()` in the code below should check the password and then call `user.loginOk/loginFail` depending on the answer. +Виклик `askPassword()` в коді наведеному нижче повинен перевіряти пароль та викликати `user.loginOk/loginFail` в залежності від відповіді. -But it leads to an error. Why? +Але виконання коду призводить до помилки. Чому? -Fix the highlighted line for everything to start working right (other lines are not to be changed). +Виправте виділений рядок, щоб код запрацював правильно (інші рядки не мають бути змінені). ```js run function askPassword(ok, fail) { - let password = prompt("Password?", ''); + let password = prompt("Пароль?", ''); if (password == "rockstar") ok(); else fail(); } let user = { - name: 'John', + name: 'Іван', loginOk() { - alert(`${this.name} logged in`); + alert(`${this.name} увійшов`); }, loginFail() { - alert(`${this.name} failed to log in`); + alert(`${this.name} виконав невдалу спробу входу`); }, }; diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md index 3284c943b..ddb3a2cbc 100644 --- a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md @@ -1,14 +1,14 @@ -1. Either use a wrapper function, an arrow to be concise: +1. Або використовуйте стрілкову функцію як функцію обгортку для короткого запису: ```js askPassword(() => user.login(true), () => user.login(false)); ``` - Now it gets `user` from outer variables and runs it the normal way. + Тепер `user` отримується з зовнішніх змінних та код виконується правильно. -2. Or create a partial function from `user.login` that uses `user` as the context and has the correct first argument: +2. Або створіть частково застосовану функцію `user.login`, що використовує `user` як контекст та має правильний аргумент: ```js diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md index c90851c2b..5c09780fd 100644 --- a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md @@ -1,27 +1,27 @@ -importance: 5 +важливість: 5 --- -# Partial application for login +# Часткове застосування для логіну -The task is a little more complex variant of . +Задача трохи складніша ніж . -The `user` object was modified. Now instead of two functions `loginOk/loginFail`, it has a single function `user.login(true/false)`. +Об'єкт `user` був змінений. Тепер замість двох функцій `loginOk/loginFail`, він має одну функцію `user.login(true/false)`. -What should we pass `askPassword` in the code below, so that it calls `user.login(true)` as `ok` and `user.login(false)` as `fail`? +Що ми маємо передати `askPassword` в коді нижче, щоб вона викликала `user.login(true)` при `ok` та `user.login(false)` при `fail`? ```js function askPassword(ok, fail) { - let password = prompt("Password?", ''); + let password = prompt("Пароль?", ''); if (password == "rockstar") ok(); else fail(); } let user = { - name: 'John', + name: 'Іван', login(result) { - alert( this.name + (result ? ' logged in' : ' failed to log in') ); + alert( this.name + (result ? ' увійшов' : ' виконав невдалу спробу входу') ); } }; @@ -30,5 +30,5 @@ askPassword(?, ?); // ? */!* ``` -Your changes should only modify the highlighted fragment. +Вносіть зміни тільки у виділений рядок. diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 3cee4fe83..e569db528 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -3,116 +3,115 @@ libs: --- -# Function binding +# Прив'язка контексту до функції -When passing object methods as callbacks, for instance to `setTimeout`, there's a known problem: "losing `this`". +Передаючи методи об'єкту в якості колбеків, наприклад в `setTimeout`, існує відома проблема: "втрата `this`". -In this chapter we'll see the ways to fix it. +В цьому розділі ми розглянемо способи як це можливо виправити. -## Losing "this" +## Втрата "this" -We've already seen examples of losing `this`. Once a method is passed somewhere separately from the object -- `this` is lost. +Ми вже розглядали приклади втрати `this`. Якщо метод передавався окремо від об'єкта -- `this` втрачається. -Here's how it may happen with `setTimeout`: +В прикладі наведено як це відбувається з `setTimeout`: ```js run let user = { - firstName: "John", + firstName: "Іван", sayHi() { - alert(`Hello, ${this.firstName}!`); + alert(`Привіт, ${this.firstName}!`); } }; *!* -setTimeout(user.sayHi, 1000); // Hello, undefined! +setTimeout(user.sayHi, 1000); // Привіт, undefined! */!* ``` -As we can see, the output shows not "John" as `this.firstName`, but `undefined`! +Як ми можемо спостерігати, модальне вікно браузера відображає не "Іван" як `this.firstName`, а `undefined`! -That's because `setTimeout` got the function `user.sayHi`, separately from the object. The last line can be rewritten as: +Це тому що `setTimeout` отримав функцію `user.sayHi` окремо від об'єкта. Останній рядок бути переписаний наступним чином: ```js let f = user.sayHi; -setTimeout(f, 1000); // lost user context +setTimeout(f, 1000); // втрата контексту об`єкта user ``` -The method `setTimeout` in-browser is a little special: it sets `this=window` for the function call (for Node.js, `this` becomes the timer object, but doesn't really matter here). So for `this.firstName` it tries to get `window.firstName`, which does not exist. In other similar cases, usually `this` just becomes `undefined`. +Метод `setTimeout` в браузері трохи особливий: він встановлює `this=window` під час виклику функції (для Node.js, `this` стане об'єкт таймеру, але це не дуже важливо у цьому випадку). Таким чином для `this.firstName` метод намагається отримати `window.firstName`, що не існує. В інших схожих випадках, зазвичай `this` просто стає `undefined`. -The task is quite typical -- we want to pass an object method somewhere else (here -- to the scheduler) where it will be called. How to make sure that it will be called in the right context? +Задача досить типова -- ми хочемо передати метод об'єкту деінде (в цьому випадку -- в планувальник) де він буде викликаний. Як бути впевненими в тому, що він буде викликаний з правильним контекстом? +## Рішення 1: обгортка -## Solution 1: a wrapper - -The simplest solution is to use a wrapping function: +Найпростіше рішення - використати функцію обгортку: ```js run let user = { - firstName: "John", + firstName: "Іван", sayHi() { - alert(`Hello, ${this.firstName}!`); + alert(`Привіт, ${this.firstName}!`); } }; *!* setTimeout(function() { - user.sayHi(); // Hello, John! + user.sayHi(); // Привіт, Іван! }, 1000); */!* ``` -Now it works, because it receives `user` from the outer lexical environment, and then calls the method normally. +Тепер це працює, тому що ми отримали `user` з зовнішнього лексичного оточення, і потім викликали метод. -The same, but shorter: +Аналогічний запис, тільки коротший: ```js -setTimeout(() => user.sayHi(), 1000); // Hello, John! +setTimeout(() => user.sayHi(), 1000); // Привіт, Іван! ``` -Looks fine, but a slight vulnerability appears in our code structure. +Виглядає чудово, але з'являється легка вразливість в структурі нашого коду. -What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, it will call the wrong object! +Що якщо перед спрацюванням `setTimeout` (з однією секундою затримки!) `user` змінить значення? Тоді, неочікувано, він викличе неправильний об'єкт! ```js run let user = { - firstName: "John", + firstName: "Іван", sayHi() { - alert(`Hello, ${this.firstName}!`); + alert(`Привіт, ${this.firstName}!`); } }; setTimeout(() => user.sayHi(), 1000); -// ...the value of user changes within 1 second +// ...значення user змінюється впродовж 1 секунди user = { - sayHi() { alert("Another user in setTimeout!"); } + sayHi() { alert("Інший user в setTimeout!"); } }; -// Another user in setTimeout! +// Інший user в setTimeout! ``` -The next solution guarantees that such thing won't happen. +Наступне рішення гарантує, що така ситуація не трапиться. -## Solution 2: bind +## Рішення 2: прив'язка -Functions provide a built-in method [bind](mdn:js/Function/bind) that allows to fix `this`. +Функції надають нам вбудований метод [bind](mdn:js/Function/bind), що дозволяє зберегти правильний `this`. -The basic syntax is: +Основний синтаксис: ```js -// more complex syntax will come a little later +// більш складний синтаксис буде трохи пізніше let boundFunc = func.bind(context); ``` -The result of `func.bind(context)` is a special function-like "exotic object", that is callable as function and transparently passes the call to `func` setting `this=context`. +Результатом `func.bind(context)` буде певний "екзотичний об'єкт", який може бути викликаний як функція та передає виклику `func` встановлений контекст `this=context`. -In other words, calling `boundFunc` is like `func` with fixed `this`. +Іншими словами, виклик `boundFunc` це як виклик `func` з виправленим `this`. -For instance, here `funcUser` passes a call to `func` with `this=user`: +Наприклад, тут `funcUser` передає виклик `func` з `this=user`: -```js run +```js run let user = { - firstName: "John" + firstName: "Іван" }; function func() { @@ -121,39 +120,39 @@ function func() { *!* let funcUser = func.bind(user); -funcUser(); // John +funcUser(); // Іван */!* ``` -Here `func.bind(user)` as a "bound variant" of `func`, with fixed `this=user`. +Тут `func.bind(user)` як "прив'язаний варіант" функції `func`, з виправленим `this=user`. -All arguments are passed to the original `func` "as is", for instance: +Всі аргументи передаються початковій функції `func` "як є", наприклад: -```js run +```js run let user = { - firstName: "John" + firstName: "Іван" }; function func(phrase) { alert(phrase + ', ' + this.firstName); } -// bind this to user +// прив'язка до user let funcUser = func.bind(user); *!* -funcUser("Hello"); // Hello, John (argument "Hello" is passed, and this=user) +funcUser("Привіт"); // Привіт, Іван (переданий аргумент "Привіт" та this=user) */!* ``` -Now let's try with an object method: +Тепер спробуємо з методом об'єкту: ```js run let user = { - firstName: "John", + firstName: "Іван", sayHi() { - alert(`Hello, ${this.firstName}!`); + alert(`Привіт, ${this.firstName}!`); } }; @@ -161,25 +160,25 @@ let user = { let sayHi = user.sayHi.bind(user); // (*) */!* -// can run it without an object -sayHi(); // Hello, John! +// можемо викликати без об'єкту +sayHi(); // Привіт, Іван! -setTimeout(sayHi, 1000); // Hello, John! +setTimeout(sayHi, 1000); // Привіт, Іван! -// even if the value of user changes within 1 second -// sayHi uses the pre-bound value which is reference to the old user object +// навіть якщо значення user зміниться впродовж 1 секунди +// sayHi використовує прив'язане значення, яке посилається на старий об'єкт user user = { - sayHi() { alert("Another user in setTimeout!"); } + sayHi() { alert("Інший user в setTimeout!"); } }; ``` -In the line `(*)` we take the method `user.sayHi` and bind it to `user`. The `sayHi` is a "bound" function, that can be called alone or passed to `setTimeout` -- doesn't matter, the context will be right. +В строчці `(*)` ми взяли метод `user.sayHi` та прив'язали його до `user`. `sayHi` є "прив'язаною" функцією, що може бути викликана окремо або передана до `setTimeout` -- не важливо, контекст буде правильний. -Here we can see that arguments are passed "as is", only `this` is fixed by `bind`: +В цьому прикладі ми можемо бачити що аргументи передані "як є", тільки `this` виправлено за допомогою `bind`: ```js run let user = { - firstName: "John", + firstName: "Іван", say(phrase) { alert(`${phrase}, ${this.firstName}!`); } @@ -187,12 +186,12 @@ let user = { let say = user.say.bind(user); -say("Hello"); // Hello, John ("Hello" argument is passed to say) -say("Bye"); // Bye, John ("Bye" is passed to say) +say("Привіт"); // Привіт, Іван (Аргумент "Привіт" переданий функції say) +say("Бувай"); // Бувай, Іван ("Бувай" передане функції say) ``` -````smart header="Convenience method: `bindAll`" -If an object has many methods and we plan to actively pass it around, then we could bind them all in a loop: +````smart header="Зручний метод: `bindAll`" +Якщо об'єкт містить багато методів та ми плануємо активно їх передавати, тоді ми можемо прив'язати їх всіх за допомогою циклу: ```js for (let key in user) { @@ -202,24 +201,24 @@ for (let key in user) { } ``` -JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(object, methodNames)](http://lodash.com/docs#bindAll) in lodash. +JavaScript бібліотеки також пропонуються функції для зручної масової прив'язки, наприклад [_.bindAll(object, methodNames)](http://lodash.com/docs#bindAll) в бібліотеці lodash. ```` -## Partial functions +## Часткове застосування -Until now we have only been talking about binding `this`. Let's take it a step further. +До цього моменту ми говорили тільки про прив'язку `this`. Зробимо крок далі. -We can bind not only `this`, but also arguments. That's rarely done, but sometimes can be handy. +Ми можемо прив'язати не тільки `this`, а також аргументи. Це робиться рідко, проте може бути інколи дуже зручним. -The full syntax of `bind`: +Повний синтаксис `bind`: ```js let bound = func.bind(context, [arg1], [arg2], ...); ``` -It allows to bind context as `this` and starting arguments of the function. +Це дозволяє прив'язати context як `this` та початкові аргументи функції. -For instance, we have a multiplication function `mul(a, b)`: +Наприклад, ми маємо функцію множення `mul(a, b)`: ```js function mul(a, b) { @@ -227,7 +226,7 @@ function mul(a, b) { } ``` -Let's use `bind` to create a function `double` on its base: +Використаємо `bind` щоб створити функцію `double` на її основі: ```js run function mul(a, b) { @@ -243,13 +242,13 @@ alert( double(4) ); // = mul(2, 4) = 8 alert( double(5) ); // = mul(2, 5) = 10 ``` -The call to `mul.bind(null, 2)` creates a new function `double` that passes calls to `mul`, fixing `null` as the context and `2` as the first argument. Further arguments are passed "as is". +Виклик `mul.bind(null, 2)` створює нову функцію `double` що передає виклик `mul`, встановлючи `null` як контекст та `2` як перший аргумент. Подальші аргументи передаються "як є". -That's called [partial function application](https://en.wikipedia.org/wiki/Partial_application) -- we create a new function by fixing some parameters of the existing one. +Це називається [часткове застосування](https://en.wikipedia.org/wiki/Partial_application) -- ми створюємо нову функцію виправляючи деякі параметри існуючої. -Please note that we actually don't use `this` here. But `bind` requires it, so we must put in something like `null`. +Зверніть увагу, що ми не використовували `this` в цьому прикладі. Проте `bind` вимагає цього, тому ми маємо передати щось як заглушку -- `null`. -The function `triple` in the code below triples the value: +Функція `triple` в коді нижче потроює значення: ```js run function mul(a, b) { @@ -265,23 +264,24 @@ alert( triple(4) ); // = mul(3, 4) = 12 alert( triple(5) ); // = mul(3, 5) = 15 ``` -Why do we usually make a partial function? +Чому ми використовуємо часткове застосування? + +Перевагою цього є те, що ми можемо створити незалежну функцію з читабельним ім'ям (`double`, `triple`). Ми можемо використовувати її та не передавати перший аргумент кожен раз, оскільки це замість нас виконує `bind`. -The benefit is that we can create an independent function with a readable name (`double`, `triple`). We can use it and not provide the first argument every time as it's fixed with `bind`. +В інших випадках, часткове застосування є корисним, коли ми маємо дуже загальну функцію та хочемо менш універсальний її варіант для зручності. -In other cases, partial application is useful when we have a very generic function and want a less universal variant of it for convenience. +Наприклад, у нас є функція `send(from, to, text)`. Тоді, в середині об'єкту `user` ми можемо захотіти використати її частковий варіант: `sendTo(to, text)`, яка відправляє текст від поточного користувача. -For instance, we have a function `send(from, to, text)`. Then, inside a `user` object we may want to use a partial variant of it: `sendTo(to, text)` that sends from the current user. +## Використання часткового застосування без контексту -## Going partial without context +Що якщо ми хочемо виправити деякі аргументи, але не контекст `this`? Наприклад, для методу об'єкта. -What if we'd like to fix some arguments, but not the context `this`? For example, for an object method. +Вбудований метод `bind` не дозволяє цього. Ми можемо просто опустити контекст та перейти до аргументів. -The native `bind` does not allow that. We can't just omit the context and jump to arguments. +На щастя, функція `partial` для прив'язування тільки аргументів може бути реалізована дуже просто. -Fortunately, a function `partial` for binding only arguments can be easily implemented. -Like this: +Як тут: ```js run *!* @@ -292,37 +292,37 @@ function partial(func, ...argsBound) { } */!* -// Usage: +// Використання: let user = { - firstName: "John", + firstName: "Іван", say(time, phrase) { alert(`[${time}] ${this.firstName}: ${phrase}!`); } }; -// add a partial method with fixed time +// та метод partial з виправленим часом user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes()); -user.sayNow("Hello"); +user.sayNow("Привіт"); // Something like: -// [10:00] John: Hello! +// [10:00] Іван: Привіт! ``` -The result of `partial(func[, arg1, arg2...])` call is a wrapper `(*)` that calls `func` with: -- Same `this` as it gets (for `user.sayNow` call it's `user`) -- Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`) -- Then gives it `...args` -- arguments given to the wrapper (`"Hello"`) +Результатом виклику `partial(func[, arg1, arg2...])` є обгортка `(*)` що викликає `func` з: +- Те ж `this` яке воно отримує (для виклику `user.sayNow` це `user`) +- Передає йому `...argsBound` -- аргументи з виклику `partial` (`"10:00"`) +- Потім передає йому `...args` -- аргументи отримані з обгортки (`"Hello"`) -So easy to do it with the spread syntax, right? +Як бачите, це легко робиться за допомогою оператору розширення, чи не так? -Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library. +Також існує реалізація [_.partial](https://lodash.com/docs#partial) в бібліотеці lodash. -## Summary +## Висновок -Method `func.bind(context, ...args)` returns a "bound variant" of function `func` that fixes the context `this` and first arguments if given. +Метод `func.bind(context, ...args)` повертає a "прив'язаний варіант" функції `func` який виправляє контекст `this` та аргументи, якщо вони передані. -Usually we apply `bind` to fix `this` for an object method, so that we can pass it somewhere. For example, to `setTimeout`. +Зазвичай ми застосовуємо `bind`, щоб виправити `this` для методу об'єкта та передати його деінде. Наприклад, в `setTimeout`. -When we fix some arguments of an existing function, the resulting (less universal) function is called *partially applied* or *partial*. +Коли ми виправляємо деякі аргументи існуючої функції, в результаті ми отримуємо (менш універсальну) функцію, яка називається *частково застосованою* або *частковою*. -Partials are convenient when we don't want to repeat the same argument over and over again. Like if we have a `send(from, to)` function, and `from` should always be the same for our task, we can get a partial and go on with it. +Часткові функції зручні, коли ми не хочемо повторно передавати одні й ті ж самі аргументи знову і знову. Наприклад, якщо ми маємо функцію `send(from, to)` та аргумент `from` постійно буде однаковим для нашої поточної задачі, ми можемо зробити частково застосовану функцію та використовувати її. From 1aa9576d1a4443c27e677d816e6c2020cadbfd72 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 25 Sep 2021 23:26:02 +0300 Subject: [PATCH 2/8] Function binding --- 1-js/06-advanced-functions/10-bind/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index e569db528..6dfe22976 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -40,6 +40,7 @@ setTimeout(f, 1000); // втрата контексту об`єкта user Метод `setTimeout` в браузері трохи особливий: він встановлює `this=window` під час виклику функції (для Node.js, `this` стане об'єкт таймеру, але це не дуже важливо у цьому випадку). Таким чином для `this.firstName` метод намагається отримати `window.firstName`, що не існує. В інших схожих випадках, зазвичай `this` просто стає `undefined`. Задача досить типова -- ми хочемо передати метод об'єкту деінде (в цьому випадку -- в планувальник) де він буде викликаний. Як бути впевненими в тому, що він буде викликаний з правильним контекстом? + ## Рішення 1: обгортка Найпростіше рішення - використати функцію обгортку: From 544c2b65873f683a5f4e5929762f509a3eb2540a Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 25 Sep 2021 23:29:17 +0300 Subject: [PATCH 3/8] Function binding --- 1-js/06-advanced-functions/10-bind/article.md | 1 - 1 file changed, 1 deletion(-) diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 6dfe22976..4e45705a9 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -281,7 +281,6 @@ alert( triple(5) ); // = mul(3, 5) = 15 На щастя, функція `partial` для прив'язування тільки аргументів може бути реалізована дуже просто. - Як тут: ```js run From b457b4766081f38548131fdd6a6eb583a72ade56 Mon Sep 17 00:00:00 2001 From: Taras Date: Sun, 26 Sep 2021 12:21:17 +0300 Subject: [PATCH 4/8] Update 1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md --- .../10-bind/2-write-to-object-after-bind/solution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md index b349d5314..b98ba59c7 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md @@ -13,6 +13,6 @@ let user = { user.g(); ``` -Контекст прив'язаної функції жорстко-фіксований. Немає способу змінити це в подальшому. +Контекст прив’язаної функції жорстко-фіксований. Немає способу змінити це в подальшому. Так чином в той час як ми запускаємо `user.g()`, функція `f` викликається з `this=null`. From 53079ccb1abc23f8e08018f6f0691894fdd84778 Mon Sep 17 00:00:00 2001 From: Taras Date: Sun, 26 Sep 2021 12:22:03 +0300 Subject: [PATCH 5/8] Update 1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md --- .../10-bind/2-write-to-object-after-bind/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md index 1fd4942db..e394f738f 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md @@ -1,4 +1,4 @@ -важливість: 5 +importance: 5 --- From 4c3d8aba32bfc39f26b8582d75caf9b4cd235b11 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 27 Sep 2021 13:23:01 +0300 Subject: [PATCH 6/8] Function binding --- .../2-write-to-object-after-bind/solution.md | 2 +- .../2-write-to-object-after-bind/task.md | 4 +- .../10-bind/3-second-bind/solution.md | 4 +- .../10-bind/3-second-bind/task.md | 6 +-- .../solution.md | 2 +- .../4-function-property-after-bind/task.md | 4 +- .../10-bind/5-question-use-bind/solution.md | 4 +- .../10-bind/5-question-use-bind/task.md | 2 +- .../10-bind/6-ask-partial/solution.md | 2 +- .../10-bind/6-ask-partial/task.md | 4 +- 1-js/06-advanced-functions/10-bind/article.md | 54 +++++++++---------- 11 files changed, 44 insertions(+), 44 deletions(-) diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md index b349d5314..b98ba59c7 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md @@ -13,6 +13,6 @@ let user = { user.g(); ``` -Контекст прив'язаної функції жорстко-фіксований. Немає способу змінити це в подальшому. +Контекст прив’язаної функції жорстко-фіксований. Немає способу змінити це в подальшому. Так чином в той час як ми запускаємо `user.g()`, функція `f` викликається з `this=null`. diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md index 1fd4942db..4de9f88e4 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md @@ -1,8 +1,8 @@ -важливість: 5 +importance: 5 --- -# Прив'язана функція як метод +# Прив’язана функція як метод Що виведе функція? diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md index dacb90668..fc209c68f 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md @@ -10,6 +10,6 @@ f = f.bind( {name: "Іван"} ).bind( {name: "Христя"} ); f(); // Іван ``` -Екзотичний об'єкт [прив'язаної функції](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) повертається від `f.bind(...)`, що запам'ятовує контекст (та аргументи, якщо передані) тільки під час створення. +Екзотичний об’єкт [прив’язаної функції](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) повертається від `f.bind(...)`, що запам’ятовує контекст (та аргументи, якщо передані) тільки під час створення. -Функція не може бути переприв'язана. +Функція не може бути переприв’язана. diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md index 06e6d2f5d..f4e12ae0e 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md @@ -1,10 +1,10 @@ -важливість: 5 +importance: 5 --- -# Друга прив'язка +# Друга прив’язка -Чи можемо ми змінити `this` за допомогою додаткового прив'язування? +Чи можемо ми змінити `this` за допомогою додаткового прив’язування? Який результат буде виведено? diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md index 5aadf02e9..fe7ba11c3 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md @@ -1,4 +1,4 @@ Відповідь: `undefined`. -Результатом `bind` є інший об'єкт. Він не містить властивість `test`. +Результатом `bind` є інший об’єкт. Він не містить властивість `test`. diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md index d81ac049f..b5f92494a 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md @@ -1,8 +1,8 @@ -важливість: 5 +importance: 5 --- -# Властивість функції після прив'язки +# Властивість функції після прив’язки Функції присвоєна властивість зі значенням. Чи зміниться вона після `bind`? Чому? diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md index b0f33e437..1e93196ec 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md @@ -1,9 +1,9 @@ -Помилка виникає тому що `askPassword` отримує функції `loginOk/loginFail` без об'єкту. +Помилка виникає тому що `askPassword` отримує функції `loginOk/loginFail` без об’єкту. Коли вона викликає їх, їх контекст втрачено `this=undefined`. -Спробуємо використати `bind`, щоб прив'язати контекст: +Спробуємо використати `bind`, щоб прив’язати контекст: ```js run function askPassword(ok, fail) { diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md index 2945bc806..784a09cb5 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md @@ -1,4 +1,4 @@ -важливість: 5 +importance: 5 --- diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md index ddb3a2cbc..83ce2da46 100644 --- a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md @@ -1,6 +1,6 @@ -1. Або використовуйте стрілкову функцію як функцію обгортку для короткого запису: +1. Або використовуйте стрілкову функцію як функцію-обгортку для короткого запису: ```js askPassword(() => user.login(true), () => user.login(false)); diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md index 5c09780fd..97feda06e 100644 --- a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md @@ -1,4 +1,4 @@ -важливість: 5 +importance: 5 --- @@ -6,7 +6,7 @@ Задача трохи складніша ніж . -Об'єкт `user` був змінений. Тепер замість двох функцій `loginOk/loginFail`, він має одну функцію `user.login(true/false)`. +Об’єкт `user` був змінений. Тепер замість двох функцій `loginOk/loginFail`, він має одну функцію `user.login(true/false)`. Що ми маємо передати `askPassword` в коді нижче, щоб вона викликала `user.login(true)` при `ok` та `user.login(false)` при `fail`? diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 4e45705a9..561b4a2cb 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -3,15 +3,15 @@ libs: --- -# Прив'язка контексту до функції +# Прив’язка контексту до функції -Передаючи методи об'єкту в якості колбеків, наприклад в `setTimeout`, існує відома проблема: "втрата `this`". +Передаючи методи об’єкту в якості колбеків, наприклад в `setTimeout`, існує відома проблема: "втрата `this`". В цьому розділі ми розглянемо способи як це можливо виправити. ## Втрата "this" -Ми вже розглядали приклади втрати `this`. Якщо метод передавався окремо від об'єкта -- `this` втрачається. +Ми вже розглядали приклади втрати `this`. Якщо метод передавався окремо від об’єкта -- `this` втрачається. В прикладі наведено як це відбувається з `setTimeout`: @@ -30,16 +30,16 @@ setTimeout(user.sayHi, 1000); // Привіт, undefined! Як ми можемо спостерігати, модальне вікно браузера відображає не "Іван" як `this.firstName`, а `undefined`! -Це тому що `setTimeout` отримав функцію `user.sayHi` окремо від об'єкта. Останній рядок бути переписаний наступним чином: +Це тому що `setTimeout` отримав функцію `user.sayHi` окремо від об’єкта. Останній рядок бути переписаний наступним чином: ```js let f = user.sayHi; setTimeout(f, 1000); // втрата контексту об`єкта user ``` -Метод `setTimeout` в браузері трохи особливий: він встановлює `this=window` під час виклику функції (для Node.js, `this` стане об'єкт таймеру, але це не дуже важливо у цьому випадку). Таким чином для `this.firstName` метод намагається отримати `window.firstName`, що не існує. В інших схожих випадках, зазвичай `this` просто стає `undefined`. +Метод `setTimeout` в браузері трохи особливий: він встановлює `this=window` під час виклику функції (для Node.js, `this` стане об’єкт таймеру, але це не дуже важливо у цьому випадку). Таким чином для `this.firstName` метод намагається отримати `window.firstName`, що не існує. В інших схожих випадках, зазвичай `this` просто стає `undefined`. -Задача досить типова -- ми хочемо передати метод об'єкту деінде (в цьому випадку -- в планувальник) де він буде викликаний. Як бути впевненими в тому, що він буде викликаний з правильним контекстом? +Задача досить типова -- ми хочемо передати метод об’єкту деінде (в цьому випадку -- в планувальник) де він буде викликаний. Як бути впевненими в тому, що він буде викликаний з правильним контекстом? ## Рішення 1: обгортка @@ -68,9 +68,9 @@ setTimeout(function() { setTimeout(() => user.sayHi(), 1000); // Привіт, Іван! ``` -Виглядає чудово, але з'являється легка вразливість в структурі нашого коду. +Виглядає чудово, але з’являється легка вразливість в структурі нашого коду. -Що якщо перед спрацюванням `setTimeout` (з однією секундою затримки!) `user` змінить значення? Тоді, неочікувано, він викличе неправильний об'єкт! +Що якщо перед спрацюванням `setTimeout` (з однією секундою затримки!) `user` змінить значення? Тоді, неочікувано, він викличе неправильний об’єкт! ```js run @@ -93,7 +93,7 @@ user = { Наступне рішення гарантує, що така ситуація не трапиться. -## Рішення 2: прив'язка +## Рішення 2: прив’язка Функції надають нам вбудований метод [bind](mdn:js/Function/bind), що дозволяє зберегти правильний `this`. @@ -104,7 +104,7 @@ user = { let boundFunc = func.bind(context); ``` -Результатом `func.bind(context)` буде певний "екзотичний об'єкт", який може бути викликаний як функція та передає виклику `func` встановлений контекст `this=context`. +Результатом `func.bind(context)` буде певний "екзотичний об’єкт", який може бути викликаний як функція та передає виклику `func` встановлений контекст `this=context`. Іншими словами, виклик `boundFunc` це як виклик `func` з виправленим `this`. @@ -125,7 +125,7 @@ funcUser(); // Іван */!* ``` -Тут `func.bind(user)` як "прив'язаний варіант" функції `func`, з виправленим `this=user`. +Тут `func.bind(user)` як "прив’язаний варіант" функції `func`, з виправленим `this=user`. Всі аргументи передаються початковій функції `func` "як є", наприклад: @@ -138,7 +138,7 @@ function func(phrase) { alert(phrase + ', ' + this.firstName); } -// прив'язка до user +// прив’язка до user let funcUser = func.bind(user); *!* @@ -146,7 +146,7 @@ funcUser("Привіт"); // Привіт, Іван (переданий аргу */!* ``` -Тепер спробуємо з методом об'єкту: +Тепер спробуємо з методом об’єкту: ```js run @@ -161,19 +161,19 @@ let user = { let sayHi = user.sayHi.bind(user); // (*) */!* -// можемо викликати без об'єкту +// можемо викликати без об’єкту sayHi(); // Привіт, Іван! setTimeout(sayHi, 1000); // Привіт, Іван! // навіть якщо значення user зміниться впродовж 1 секунди -// sayHi використовує прив'язане значення, яке посилається на старий об'єкт user +// sayHi використовує прив’язане значення, яке посилається на старий об’єкт user user = { sayHi() { alert("Інший user в setTimeout!"); } }; ``` -В строчці `(*)` ми взяли метод `user.sayHi` та прив'язали його до `user`. `sayHi` є "прив'язаною" функцією, що може бути викликана окремо або передана до `setTimeout` -- не важливо, контекст буде правильний. +В строчці `(*)` ми взяли метод `user.sayHi` та прив’язали його до `user`. `sayHi` є "прив’язаною" функцією, що може бути викликана окремо або передана до `setTimeout` -- не важливо, контекст буде правильний. В цьому прикладі ми можемо бачити що аргументи передані "як є", тільки `this` виправлено за допомогою `bind`: @@ -192,7 +192,7 @@ say("Бувай"); // Бувай, Іван ("Бувай" передане фун ``` ````smart header="Зручний метод: `bindAll`" -Якщо об'єкт містить багато методів та ми плануємо активно їх передавати, тоді ми можемо прив'язати їх всіх за допомогою циклу: +Якщо об’єкт містить багато методів та ми плануємо активно їх передавати, тоді ми можемо прив’язати їх всіх за допомогою циклу: ```js for (let key in user) { @@ -202,14 +202,14 @@ for (let key in user) { } ``` -JavaScript бібліотеки також пропонуються функції для зручної масової прив'язки, наприклад [_.bindAll(object, methodNames)](http://lodash.com/docs#bindAll) в бібліотеці lodash. +JavaScript бібліотеки також пропонуються функції для зручної масової прив’язки, наприклад [_.bindAll(object, methodNames)](http://lodash.com/docs#bindAll) в бібліотеці lodash. ```` ## Часткове застосування -До цього моменту ми говорили тільки про прив'язку `this`. Зробимо крок далі. +До цього моменту ми говорили тільки про прив’язку `this`. Зробимо крок далі. -Ми можемо прив'язати не тільки `this`, а також аргументи. Це робиться рідко, проте може бути інколи дуже зручним. +Ми можемо прив’язати не тільки `this`, а також аргументи. Це робиться рідко, проте може бути інколи дуже зручним. Повний синтаксис `bind`: @@ -217,7 +217,7 @@ JavaScript бібліотеки також пропонуються функці let bound = func.bind(context, [arg1], [arg2], ...); ``` -Це дозволяє прив'язати context як `this` та початкові аргументи функції. +Це дозволяє прив’язати context як `this` та початкові аргументи функції. Наприклад, ми маємо функцію множення `mul(a, b)`: @@ -267,19 +267,19 @@ alert( triple(5) ); // = mul(3, 5) = 15 Чому ми використовуємо часткове застосування? -Перевагою цього є те, що ми можемо створити незалежну функцію з читабельним ім'ям (`double`, `triple`). Ми можемо використовувати її та не передавати перший аргумент кожен раз, оскільки це замість нас виконує `bind`. +Перевагою цього є те, що ми можемо створити незалежну функцію з читабельним ім’ям (`double`, `triple`). Ми можемо використовувати її та не передавати перший аргумент кожен раз, оскільки це замість нас виконує `bind`. В інших випадках, часткове застосування є корисним, коли ми маємо дуже загальну функцію та хочемо менш універсальний її варіант для зручності. -Наприклад, у нас є функція `send(from, to, text)`. Тоді, в середині об'єкту `user` ми можемо захотіти використати її частковий варіант: `sendTo(to, text)`, яка відправляє текст від поточного користувача. +Наприклад, у нас є функція `send(from, to, text)`. Тоді, в середині об’єкту `user` ми можемо захотіти використати її частковий варіант: `sendTo(to, text)`, яка відправляє текст від поточного користувача. ## Використання часткового застосування без контексту -Що якщо ми хочемо виправити деякі аргументи, але не контекст `this`? Наприклад, для методу об'єкта. +Що якщо ми хочемо виправити деякі аргументи, але не контекст `this`? Наприклад, для методу об’єкта. Вбудований метод `bind` не дозволяє цього. Ми можемо просто опустити контекст та перейти до аргументів. -На щастя, функція `partial` для прив'язування тільки аргументів може бути реалізована дуже просто. +На щастя, функція `partial` для прив’язування тільки аргументів може бути реалізована дуже просто. Як тут: @@ -319,9 +319,9 @@ user.sayNow("Привіт"); ## Висновок -Метод `func.bind(context, ...args)` повертає a "прив'язаний варіант" функції `func` який виправляє контекст `this` та аргументи, якщо вони передані. +Метод `func.bind(context, ...args)` повертає a "прив’язаний варіант" функції `func` який виправляє контекст `this` та аргументи, якщо вони передані. -Зазвичай ми застосовуємо `bind`, щоб виправити `this` для методу об'єкта та передати його деінде. Наприклад, в `setTimeout`. +Зазвичай ми застосовуємо `bind`, щоб виправити `this` для методу об’єкта та передати його деінде. Наприклад, в `setTimeout`. Коли ми виправляємо деякі аргументи існуючої функції, в результаті ми отримуємо (менш універсальну) функцію, яка називається *частково застосованою* або *частковою*. From cf9db4e53df29d2c32d4f97205cecdb474fc2b18 Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 30 Sep 2021 20:57:36 +0300 Subject: [PATCH 7/8] Update 1-js/06-advanced-functions/10-bind/article.md --- 1-js/06-advanced-functions/10-bind/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 561b4a2cb..e5783b1f3 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -34,7 +34,7 @@ setTimeout(user.sayHi, 1000); // Привіт, undefined! ```js let f = user.sayHi; -setTimeout(f, 1000); // втрата контексту об`єкта user +setTimeout(f, 1000); // втрата контексту об’єкта user ``` Метод `setTimeout` в браузері трохи особливий: він встановлює `this=window` під час виклику функції (для Node.js, `this` стане об’єкт таймеру, але це не дуже важливо у цьому випадку). Таким чином для `this.firstName` метод намагається отримати `window.firstName`, що не існує. В інших схожих випадках, зазвичай `this` просто стає `undefined`. From c6870e33d2c4c593ca771a8cc3f0020768d96154 Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 30 Sep 2021 20:59:44 +0300 Subject: [PATCH 8/8] Update 1-js/06-advanced-functions/10-bind/article.md --- 1-js/06-advanced-functions/10-bind/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index e5783b1f3..0eb6fd754 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -317,7 +317,7 @@ user.sayNow("Привіт"); Також існує реалізація [_.partial](https://lodash.com/docs#partial) в бібліотеці lodash. -## Висновок +## Підсумки Метод `func.bind(context, ...args)` повертає a "прив’язаний варіант" функції `func` який виправляє контекст `this` та аргументи, якщо вони передані.