A bound function is a function bind with an object using fn.bind(obj) method. As a result of bind call we receive new function with a this bound to obj forever. .bind() makes a permanent context link and will always keep it.
The original and bound functions share the same code and scope, but different contexts on execution. this is the first argument of .bind() when invoking a bound function.
fun.bind(thisArg, [arg1, arg2, ...])
thisArg value to be passed as the this parameter to the target function when the bound function is called. The value is ignored if the bound function is constructed using the new operator.
[arg1, arg2, ...] - arguments provided to the bound function when invoking the target function.
In general, .bind function is equals to following code:
Методы call/apply вызывают функцию с заданным контекстом и аргументами. А bind не вызывает функцию. Он только возвращает «обёртку», которую мы можем вызвать позже, и которая передаст вызов в исходную функцию, с привязанным контекстом.
Use bind to carry function:
Карринг (currying) или каррирование – термин функционального программирования, который означает создание новой функции путём фиксирования аргументов существующей.
При помощи bind удобно выполнять каррирование функции:
functionmul(a, b) {return a * b;}// double умножает только на дваvar double =mul.bind(null,2); // контекст фиксируем null, он не используетсяdouble(3); // = mul(2, 3) = 6double(4); // = mul(2, 4) = 8double(5); // = mul(2, 5) = 10
Говорят, что double является частичной функцией (partial function) от mul.
Decorate functions with bind
Через функцию bind и привязку контекста очень удобно делать функции-декораторы поверх других функций. Создадим декоратор, замеряющий время выполнения функции. Он будет называться timingDecorator и получать функцию вместе с «названием таймера», а возвращать — функцию-обёртку, которая измеряет время и прибавляет его в специальный объект timer по свойству-названию:
Декораторы можно не только повторно использовать, но и комбинировать!
Это кардинально повышает их выразительную силу. Декораторы можно рассматривать как своего рода возможности, которые можно «нацепить» на любую функцию. Можно один, а можно несколько.
const timers = {};
// прибавит время выполнения f к таймеру timers[timer]
function timingDecorator(f, timer) {
return function() {
const start = performance.now();
const result = f.apply(this, arguments); // (*)
if (!timers[timer]) timers[timer] = 0;
timers[timer] += performance.now() - start;
return result;
};
}
// функция может быть произвольной, например такой:
function fibonacci(n) {
return n > 2 ? fibonacci(n - 1) + fibonacci(n - 2) : 1;
}
// использование: завернём fibonacci в декоратор
fibonacci = timingDecorator(fibonacci, "fibo");
// неоднократные вызовы...
fibonacci(10); // 55
fibonacci(20); // 6765
// ...
// в любой момент можно получить общее количество времени на вызовы
alert(timers.fibo + "мс");