You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/02-first-steps/14-function-basics/article.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -340,9 +340,15 @@ return*!*;*/!*
340
340
(some + long + expression + or + whatever *f(a) +f(b))
341
341
```
342
342
343
+
<<<<<<< HEAD
343
344
Таким образом, это фактически стало пустым `return`.
344
345
345
346
Если мы хотим, чтобы возвращаемое выражение занимало несколько строк, нужно начать его на той же строке, что и `return`. Или, хотя бы, поставить там открывающую скобку, вот так:
347
+
=======
348
+
So, it effectively becomes an empty return.
349
+
350
+
If we want the returned expression to wrap across multiple lines, we should start it at the same line as `return`. Or at least put the opening parentheses there as follows:
Перед тем, как мы рассмотрим, как можно записать это гораздо короче, давайте обратим внимание, что в браузере (и в отдельных случаях на стороне сервера) подобное использование функций очень распространено. Основным отличием между реализацией таких функций в реальном проекте и примером выше является то, что в реальности функции используют более сложные способы взаимодействия с пользователем, чем простой вызов `confirm`. В браузерах такие функции обычно отображают красивые диалоговые окна. Но это уже другая история.
134
134
135
+
<<<<<<< HEAD
135
136
**Аргументы функции `ask` ещё называют *функциями-колбэками* или просто *колбэками*.**
137
+
=======
138
+
**The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.**
139
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
136
140
137
141
Ключевая идея в том, что мы передаём функцию и ожидаем, что она вызовется обратно (от англ. "call back" - обратный вызов) когда-нибудь позже, если это будет необходимо. В нашем случае, `showOk` становится *колбэком*' для ответа "yes", а `showCancel` -- для ответа "no".
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/10-bind/article.md
+84Lines changed: 84 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -194,28 +194,49 @@ for (let key in user) {
194
194
Некоторые JS-библиотеки предоставляют встроенные функции для удобной массовой привязки контекста, например [_.bindAll(obj)](http://lodash.com/docs#bindAll) в lodash.
195
195
````
196
196
197
+
<<<<<<< HEAD
197
198
## Частичное применение
198
199
199
200
До сих пор мы говорили только о привязывании `this`. Давайте шагнём дальше.
200
201
201
202
Мы можем привязать не только `this`, но и аргументы. Это делается редко, но иногда может быть полезно.
202
203
203
204
Полный синтаксис `bind`:
205
+
=======
206
+
## Partial functions
207
+
208
+
Until now we have only been talking about binding `this`. Let's take it a step further.
209
+
210
+
We can bind not only `this`, but also arguments. That's rarely done, but sometimes can be handy.
211
+
212
+
The full syntax of `bind`:
213
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
204
214
205
215
```js
206
216
let bound = func.bind(context, [arg1], [arg2], ...);
207
217
```
218
+
<<<<<<< HEAD
208
219
Это позволяет привязать контекст `this` и начальные аргументы функции.
209
220
210
221
Например, у нас есть функция умножения `mul(a, b)`:
222
+
=======
223
+
224
+
It allows to bind context as `this` and starting arguments of the function.
225
+
226
+
For instance, we have a multiplication function `mul(a, b)`:
227
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
211
228
212
229
```js
213
230
function mul(a, b) {
214
231
return a * b;
215
232
}
216
233
```
217
234
235
+
<<<<<<< HEAD
218
236
Давайте воспользуемся `bind`, чтобы создать функцию `double` на её основе:
237
+
=======
238
+
Let's use `bind` to create a function `double` on its base:
Вызов `mul.bind(null, 2)` создаёт новую функцию `double`, которая передаёт вызов `mul`, фиксируя `null` как контекст и `2` -- как первый аргумент. Следующие аргументы передаются "как есть".
235
257
236
258
Это называется [частичное применение](https://ru.wikipedia.org/wiki/Частичное_применение) -- мы создаём новую функцию, фиксируя некоторые из существующих параметров.
237
259
238
260
Обратите внимание, что в данном случае мы на самом деле не используем `this`. Но для `bind` это обязательный параметр, так что мы должны передать туда что-нибудь вроде `null`.
239
261
240
262
В следующем коде функция `triple` умножает значение на три:
263
+
=======
264
+
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".
265
+
266
+
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.
267
+
268
+
Please note that here we actually don't use `this` here. But `bind` requires it, so we must put in something like `null`.
269
+
270
+
The function `triple` in the code below triples the value:
Для чего мы обычно создаём частично применённую функцию?
257
289
258
290
Польза от этого в том, что возможно создать независимую функцию с понятным названием (`double`, `triple`). Мы можем использовать её и не передавать каждый раз первый аргумент, т.к. он зафиксирован с помощью `bind`.
К счастью, лекго создать вспомогательную функцию `partial`, которая привязывает только аргументы.
271
303
272
304
Вот так:
305
+
=======
306
+
Why do we usually make a partial function?
307
+
308
+
The benefit is that we can create an independent function with a readable name (`double`, `triple`). We can use it and not provide first argument of every time as it's fixed with `bind`.
309
+
310
+
In other cases, partial application is useful when we have a very generic function and want a less universal variant of it for convenience.
311
+
312
+
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.
313
+
314
+
## Going partial without context
315
+
316
+
What if we'd like to fix some arguments, but not the context `this`? For example, for an object method.
317
+
318
+
The native `bind` does not allow that. We can't just omit the context and jump to arguments.
319
+
320
+
Fortunately, a helper function `partial` for binding only arguments can be easily implemented.
321
+
322
+
Like this:
323
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
273
324
274
325
```js run
275
326
*!*
@@ -280,14 +331,19 @@ function partial(func, ...argsBound) {
280
331
}
281
332
*/!*
282
333
334
+
<<<<<<< HEAD
283
335
// использование:
336
+
=======
337
+
// Usage:
338
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
284
339
let user = {
285
340
firstName: "John",
286
341
say(time, phrase) {
287
342
alert(`[${time}] ${this.firstName}: ${phrase}!`);
288
343
}
289
344
};
290
345
346
+
<<<<<<< HEAD
291
347
// добавляем частично применённый метод с фиксированным временем
292
348
user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
293
349
@@ -310,7 +366,35 @@ user.sayNow("Hello");
310
366
Метод `bind` возвращает "привязанный вариант" функции `func`, фиксируя контекст `this` и первые аргументы `arg1`, `arg2`..., если они заданы.
311
367
312
368
Обычно `bind` применяется для фиксации `this` в методе объекта, чтобы передать его в качестве колбэка. Например, для `setTimeout`.
369
+
=======
370
+
// add a partial method with fixed time
371
+
user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
372
+
373
+
user.sayNow("Hello");
374
+
// Something like:
375
+
// [10:00] John: Hello!
376
+
```
377
+
378
+
The result of `partial(func[, arg1, arg2...])` call is a wrapper `(*)` that calls `func` with:
379
+
- Same `this` as it gets (for `user.sayNow` call it's `user`)
380
+
- Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`)
381
+
- Then gives it `...args` -- arguments given to the wrapper (`"Hello"`)
382
+
383
+
So easy to do it with the spread operator, right?
384
+
385
+
Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library.
386
+
387
+
## Summary
388
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
313
389
314
390
Когда мы привязываем аргументы, такая функция называется "частично применённой" или "частичной".
315
391
392
+
<<<<<<< HEAD
316
393
Частичное применение удобно, когда мы не хотим повторять один и тот же аргумент много раз. Например, когда у нас есть функция `send(from, to)`, и `from` всё время будет одинаков для нашей задачи, мы можем создать частично применённую функцию и дальше работать с ней.
394
+
=======
395
+
Usually we apply `bind` to fix `this` for an object method, so that we can pass it somewhere. For example, to `setTimeout`.
396
+
397
+
When we fix some arguments of an existing function, the resulting (less universal) function is called *partially applied* or *partial*.
398
+
399
+
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.
user.name="Pete"; // Ошибка: Невозможно изменить доступное только для чтения свойство 'name'
125
+
=======
126
+
user.name="Pete"; // Error: Cannot assign to read only property 'name'
127
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
120
128
*/!*
121
129
```
122
130
@@ -126,27 +134,44 @@ user.name = "Pete"; // Ошибка: Невозможно изменить до
126
134
В нестрогом режиме, без `use strict`, мы не увидим никаких ошибок при записи в свойства "только для чтения" и т.п. Но эти операции всё равно не будут выполнены успешно. Действия, нарушающие ограничения флагов, в нестрогом режиме просто молча игнорируются.
127
135
```
128
136
137
+
<<<<<<< HEAD
129
138
Вот тот же пример, но свойство создано "с нуля":
139
+
=======
140
+
Here's the same example, but the property is created from scratch:
141
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
130
142
131
143
```js run
132
144
let user = { };
133
145
134
146
Object.defineProperty(user, "name", {
135
147
*!*
136
148
value:"John",
149
+
<<<<<<<HEAD
137
150
// для нового свойства необходимо явно указывать все флаги, для которых значение true
151
+
=======
152
+
// for new properties need to explicitly list what's true
153
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
138
154
enumerable:true,
139
155
configurable:true
140
156
*/!*
141
157
});
142
158
143
159
alert(user.name); // John
160
+
<<<<<<<HEAD
144
161
user.name="Pete"; // Ошибка
145
162
```
146
163
147
164
## Неперечислимое свойство
148
165
149
166
Теперь добавим собственный метод `toString` к объекту `user`.
167
+
=======
168
+
user.name = "Pete"; // Error
169
+
```
170
+
171
+
## Non-enumerable
172
+
173
+
Now let's add a custom `toString` to `user`.
174
+
>>>>>>> e50185af4b4df7dbe1870215e382a206241c8515
150
175
151
176
Встроенный метод `toString` в объектах - неперечислимый, его не видно в цикле `for..in`. Но если мы напишем свой собственный метод `toString`, цикл `for..in` будет выводить его по умолчанию:
0 commit comments