update func
This commit is contained in:
64
docs/javascript/04-functions/10-apply-context.md
Normal file
64
docs/javascript/04-functions/10-apply-context.md
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
# Привязка контекста к функции
|
||||
Источник: [https://learn.javascript.ru/bind](https://learn.javascript.ru/bind)
|
||||
|
||||
При передаче методов объекта в качестве колбэков, например для setTimeout, возникает известная проблема – потеря this.
|
||||
|
||||
Метод `bind` возвращает «привязанный вариант» функции `func`, фиксируя контекст `this` и первые аргументы `arg1`, `arg2…`, если они заданы.
|
||||
|
||||
Обычно `bind` применяется для фиксации `this` в методе объекта, чтобы передать его в качестве колбэка. Например, для `setTimeout`.
|
||||
|
||||
Когда мы привязываем аргументы, такая функция называется «частично применённой» или «частичной».
|
||||
|
||||
Частичное применение удобно, когда мы не хотим повторять один и тот же аргумент много раз. Например, если у нас есть функция send(from, to) и from всё время будет одинаков для нашей задачи, то мы можем создать частично применённую функцию и дальше работать с ней.
|
||||
|
||||
## Потеря «this»
|
||||
Мы уже видели примеры потери `this`. Как только метод передаётся отдельно от объекта – `this` теряется.
|
||||
|
||||
```js
|
||||
let user = {
|
||||
firstName: "Вася",
|
||||
sayHi() {
|
||||
alert(`Привет, ${this.firstName}!`);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(user.sayHi, 1000); // Привет, undefined!
|
||||
```
|
||||
Это произошло потому, что setTimeout получил функцию sayHi отдельно от объекта user (именно здесь функция и потеряла контекст).
|
||||
|
||||
> Метод setTimeout в браузере имеет особенность: он устанавливает this=window для вызова функции (в Node.js this становится объектом таймера, но здесь это не имеет значения). Таким образом, для this.firstName он пытается получить window.firstName, которого не существует. В других подобных случаях this обычно просто становится undefined.
|
||||
|
||||
## Решение 1: сделать функцию-обёртку
|
||||
Самый простой вариант решения – это обернуть вызов в анонимную функцию, создав замыкание:
|
||||
```js
|
||||
let user = {
|
||||
firstName: "Вася",
|
||||
sayHi() {
|
||||
alert(`Привет, ${this.firstName}!`);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
user.sayHi(); // Привет, Вася!
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
## Решение 2: привязать контекст с помощью bind
|
||||
Результатом вызова `func.bind(context)` является особый «экзотический объект» (термин взят из спецификации), который вызывается как функция и прозрачно передаёт вызов в `func`, при этом устанавливая `this=context`.
|
||||
|
||||
Другими словами, вызов boundFunc подобен вызову `func` с фиксированным `this`.
|
||||
```js
|
||||
let user = {
|
||||
firstName: "Вася",
|
||||
sayHi() {
|
||||
alert(`Привет, ${this.firstName}!`);
|
||||
}
|
||||
};
|
||||
let sayHi = user.sayHi.bind(user); // (*)
|
||||
sayHi(); // Привет, Вася!
|
||||
setTimeout(sayHi, 1000); // Привет, Вася!
|
||||
```
|
||||
Reference in New Issue
Block a user