Решение 3: встроенный метод bind
В современном JavaScript (или при подключении библиотеки es5‑shim для IE8‑) у функций уже есть встроенный метод bind , который мы можем использовать.
Он работает примерно так же, как bind , который описан выше. Изменения очень небольшие:
function f(a, b) { alert( this ); alert( a + b );
}
// вместо
// var g = bind(f, "Context"); var g = f.bind("Context"); g(1, 2); // Context, затем 3
Синтаксис встроенного bind :
var wrapper = func.bind(context[, arg1, arg2...])
func
Произвольная функция
context
Контекст, который привязывается к func
arg1 , arg2 , …
Если указаны аргументы arg1, arg2... – они будут прибавлены к каждому вызову новой функции, причем встанут перед теми, которые указаны при вызове.
Результат вызова func.bind(context) аналогичен вызову bind(func, context) , описанному выше. То есть, wrapper – это обёртка, фиксирующая контекст и передающая вызовы в func . Также можно указать аргументы, тогда и они будут фиксированы, но об этом чуть позже.
Пример со встроенным методом bind :
var user = { firstName: "Вася", sayHi: function() {
alert( this.firstName );
}
};
// setTimeout( bind(user.sayHi, user), 1000 ); setTimeout(user.sayHi.bind(user), 1000); // аналог через встроенный метод
Получили простой и надёжный способ привязать контекст, причём даже встроенный в JavaScript. Далее мы будем использовать именно встроенный метод bind .
Карринг
До этого мы говорили о привязке контекста. Теперь пойдём на шаг дальше. Привязывать можно не только контекст, но и аргументы. Используется это реже, но бывает полезно.
Карринг (currying) или каррирование – термин функционального программирования , который означает создание новой функции путём фиксирования аргументов существующей.
Как было сказано выше, метод func.bind(context, ...) может создавать обёртку, которая фиксирует не только контекст, но и ряд аргументов функции.
Например, есть функция умножения двух чисел mul(a, b) :
function mul(a, b) { return a * b;
};
При помощи bind создадим функцию double , удваивающую значения. Это будет вариант функции mul с фиксированным первым аргументом:
// double умножает только на два
var double = mul.bind(null, 2); // контекст фиксируем null, он не используется
alert( double(3) ); // = mul(2, 3) = 6 alert( double(4) ); // = mul(2, 4) = 8 alert( double(5) ); // = mul(2, 5) = 10
При вызове double будет передавать свои аргументы исходной функции mul после тех, которые указаны в bind , то есть в данном случае после зафиксированного первого аргумента 2 .
Говорят, что double является «частичной функцией» (partial function) от mul .
Другая частичная функция triple утраивает значения:
var triple = mul.bind(null, 3); // контекст фиксируем null, он не используется
alert( triple(3) ); // = mul(3, 3) = 9 alert( triple(4) ); // = mul(3, 4) = 12 alert( triple(5) ); // = mul(3, 5) = 15
При помощи bind мы можем получить из функции её «частный вариант» как самостоятельную функцию и дальше передать в setTimeout или сделать с ней что‑то ещё.
Наш выигрыш состоит в том, что эта самостоятельная функция, во‑первых, имеет понятное имя ( double , triple ), а во‑вторых, повторные вызовы позволяют не указывать каждый раз первый аргумент, он уже фиксирован благодаря bind .
Do'stlaringiz bilan baham: |