Каррирование функций — это метод превращения функции, которая принимает несколько аргументов, в новую функцию, которая принимает один аргумент (первый аргумент исходной функции) и возвращает новую функцию, которая принимает оставшиеся аргументы и возвращает результат.
Само по себе каррирование фактически фиксирует ожидаемый параметр и возвращает конкретную функцию, которая обрабатывает специфические потребности пакета. Это увеличивает применимость функции, но также снижает применимость функции.
общее определение
function currying(fn){
var slice = Array.prototype.slice;
_args = slice.call(arguments,1);
return function(){
var _inargs = slice.call(arguments);
return fn.apply(null,_args.concat(_inargs))
}
}
Полезность каррирования проявляется во многом:
Улучшить применимость.
Универсальные функции разрешают проблемы совместимости, но также будут приносить неудобства, разные сценарии приложений часто для обеспечения множества параметров, которые достигли определенной цели. Иногда он будет использоваться неоднократно для того же правила. Это вызывает взаимность кода.
function square(i){
return i * i;
}
function dubble(i){
return i *= 2;
}
function map(handeler,list){
return list.map(handeler)
}
// 数组的每一项平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);
map(square, [10, 20, 30, 40, 50]);
// 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);
map(dubble, [10, 20, 30, 40, 50]);
В этом примере создается общая функция карты для адаптации к различным сценариям приложений. Очевидно, что универсальность не вызывает сомнений. При этом в примере многократно передаются одни и те же обработчики: Square и dubble.
В приложениях может быть больше этого. Конечно, усиление общности неизбежно приведет к ослаблению применимости. Тем не менее, мы все еще можем найти баланс посередине.
См. ниже, давайте используем каррирование, чтобы преобразовать его:
function square(i) {
return i * i;
}
function dubble(i) {
return i *= 2;
}
function map(handeler, list) {
return list.map(handeler);
}
var mapSQ = currying(map, square);
mapSQ([1, 2, 3, 4, 5]);
mapSQ([6, 7, 8, 9, 10]);
mapSQ([10, 20, 30, 40, 50]);
var mapDB = currying(map, dubble);
mapDB([1, 2, 3, 4, 5]);
mapDB([6, 7, 8, 9, 10]);
mapDB([10, 20, 30, 40, 50]);Мы сужаем применимость функции, но в то же время улучшаем приспособленность функции.
Отсюда видно, что каррирование не только улучшает рациональность кода, но и выделяет идею ---Уменьшите область применения, улучшите применимость.
Давайте посмотрим на другой пример, один с более широким приложением и более знакомым:
function Ajax() {
this.xhr = new XMLHttpRequest();
}
Ajax.prototype.open = function(type, url, data, callback) {
this.onload = function() {
callback(this.xhr.responseText, this.xhr.status, this.xhr);
}
this.xhr.open(type, url, data.async);
this.xhr.send(data.paras);
}
'get post'.split(' ').forEach(function(mt) {
Ajax.prototype[mt] = currying(Ajax.prototype.open, mt);
});
var xhr = new Ajax();
xhr.get('/articles/list.php', {},
function(datas) {
// done(datas)
});
var xhr1 = new Ajax();
xhr1.post('/articles/add.php', {},
function(datas) {
// done(datas)
});
2 Задержка выполнения.
Другой вариант использования каррирования — отложенное выполнение. Непрерывное каррирование, накопление входящих параметров и, наконец, выполнение.
смотреть вниз:
var add = function() {
var _this = this,
_args = arguments
return function() {
if (!arguments.length) {
var sum = 0;
for (var i = 0,c; c = _args[i++];){
sum += c;
}
return sum
} else {
Array.prototype.push.apply(_args, arguments) return arguments.callee
}
}
}
add(1)(2)(3)(4)();//10
Общее написание:
var curry = function(fn) {
var _args = []
return function cb() {
if (arguments.length == 0) {
return fn.apply(this, _args)
}
Array.prototype.push.apply(_args, arguments);
return cb;
}
}Приведенный выше накопительный пример, можете ли вы поэкспериментировать, как его написать?
3 Фиксированные переменные.
Функция каррирования определяет сценарий ее применения. Переменные факторы и параметры фиксируются заранее, чтобы создать более явную прикладную функцию. Наиболее типичным репрезентативным приложением является функция связывания для фиксации этого объекта переменной.
Function.prototype.bind = function(context) {
var _this = this,
_args = Array.prototype.slice.call(arguments, 1);
return function() {
return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments)))
}
}