Метод функций bind своими руками
Основы основ
Чтобы указать контекст выполнения любой функций вы можете использовать три метода: call
, apply
и bind
. При использовании первых двух методов происходит вызов функции “на месте”, метод bind
функцию не вызывает, вместо этого он возвращает новую функцию с заданным контекстом. Разберёмся в простом примере, чтобы понять, как работает метод bind
:
var sum = function(a, b) {
return this.sum + a + b;
};
Изначально, при запуске в глобальной области видимости функция будет использовать объект window в качестве контекста, поэтому если попробовать её вызвать без задания контекста, вы получите не самый очевидный рельтат:
// Вызов функции, контекстом является window
sum(1, 2);
// Результат выполнения
"function (a, b) {
return this.sum + a + b;
}12"
При инициализации переменной sum с помощью оператора var
происходит запись анонимной функции в глобальную область видимости (объект window в браузере). Именно поэтому результатом выполнения функции является такое странное значение. Работает это следующим образом:
- При создании переменной sum в глобальной области видимости в объект window записывается соответствующее свойство.
- При выполнении функции контекстом является объект window, то есть this ссылается на window.
- При использовании оператора сложения будет произведено автоматическое приведение типов
Чтобы указать функции sum контекст выполнения воспользуемся метод bind:
var bindedSum = sum.bind({
sum: 10
});
bindedSum(1, 2); // 13
Метод bind вернул новую функцию, привязанную к контексту обозначенного объекта. Сама функция sum при этом не была изменена.
Но это ещё не всё, что может предложить bind. При создании новой функции также можно указать неограниченное количество аргументов, с которыми данная функция будет вызвана. Чтобы лучше проиллюстрировать этот и дальнейшие примеры перепишем функцию sum так, чтобы она складывала неограниченное количество аргументов:
var sum = function() {
return [].reduce.call(arguments, function(result, current) {
return result + current;
}, this.sum);
};
// Привязка контекста и нескольких аргуметов
var bindedSum = sum.bind({ sum: 10 }, 20, 30);
bindedSum(40, 50); // 10 + 20 + 30 + 40 + 50 === 150
Подобным образом мы можем передавать любое количество аргументов в sum, как на этапе привязки к контексту, так и при вызове новой функций.
Bind своими руками
Вы получили хитрое задание: вам необходимо реализовать метод bind самостоятельно в виде функции, сам метод bind, естественно, использовать нельзя. Не паникуйте, у вас ещё остались методы call и apply. Для начала, обозначим себе три правила:
- Функция
bind
принимает неограниченное количество аргументов, но первый и второй отвечают за саму функцию, которой будет задаваться контекст, и сам контекст соответственно. Все остальные агрументы должны быть переданы в функцию. - Функция
bind
не вызывает передаваемую ей функцию, а лишь задаёт для неё контекст. - Получаемой при помощи
bind
функции можно передать неограниченное количество аргументов, которые будут использованы по мере надобности.
var bind = function(fn, context) {
// обрезаем ненужные аргументы (функцию и контекст)
var bindArgs = [].slice.call(arguments, 2);
return function() {
// здесь все аргументы будут необходимы
var fnArgs = [].slice.call(arguments);
// собираем все
return fn.apply(context, bindArgs.concat(fnArgs));
};
};
Написанная выше функция bind работает точно также, как и метод bind:
var bindedSum = bind(sum, {sum: 10}, 20, 30);
bindedSum(40, 50, 60); // 210
Комментарии