JS реализует каррированные функции шаг за шагом

JavaScript
JS реализует каррированные функции шаг за шагом

Введение

Прежде всего, что такое карри?

Проще говоря, если есть функция, которая принимает несколько параметров, то, как правило, все параметры передаются одновременно и выполняются.
А после каррирования становитсяПараметры могут быть получены несколько раз.

выполнить

Этап 1

Теперь есть функция добавления:

function add(x, y, z) {
  return x + y + z
}

Метод вызоваadd(1, 2, 3).

Если выполняется каррирование, оно становитсяcurriedAdd(), От эффекта, примерно становитсяcurriedAdd(1)(2)(3)так.

Теперь давайте не будем смотреть, как выполнить каррирование исходной функции, а перепишем функцию в соответствии с этим методом вызова.
Код может выглядеть так:

function curriedAdd1(x) {
  return function (y) {
    return function (z) {
      return x + y + z
    }
  }
}

Этап 2

Если вы хотите выполнить обновление сейчас, вы можете принять более трех параметров.
можно использоватьargumentsили используйте оператор расширения для обработки входящих аргументов.

Но есть производная проблема. Потому что раньше можно передать только один раз, а всего можно передать только три, что гарантирует, что количество параметров будет достаточно после трех вызовов, и функция может быть выполнена.

Поскольку мы собираемся изменить его, чтобы он принимал любое количество аргументов, нам нужно указать конечную точку. Например, можно указать, что когда больше не передаются параметры, функция выполняется.

Ниже приведено использованиеargumentsреализация.

function getCurriedAdd() {
  // 在外部维护一个数组保存传递的变量
  let args_arr = []
  // 返回一个闭包
  let closure = function () {
    // 本次调用传入的参数
    let args = Array.prototype.slice.call(arguments)
    // 如果传进了新的参数
    if (args.length > 0) {
      // 保存参数
      args_arr = args_arr.concat(args)
      // 再次返回闭包,等待下次调用
      // 也可以 return arguments.callee
      return closure
    }
    // 没有传递参数,执行累加
    return args_arr.reduce((total, current) => total + current)
  }
  return closure
}
curriedAdd = getCurriedAdd()
curriedAdd(1)(2)(3)(4)()

Этап 3

В это время можно обнаружить, что вся функция выше связана с конкретной функцией функции (здесь выполняется сложение), только часть, когда параметры не передаются, а остальные части - как получить несколько параметров раз.

Тогда просто позвольтеgetCurriedAddПримите функцию в качестве параметра, замените строку кода, если параметр не передан, и вы сможете реализовать общую каррированную функцию.

Измените приведенное выше, чтобы реализовать общую каррированную функцию и каррированную факториальную функцию:

function currying(fn) {
  let args_arr = []
  let closure =  function (...args) {
    if (args.length > 0) {
      args_arr = args_arr.concat(args)
      return closure
    }
    // 没有新的参数,执行函数
    return fn(...args_arr)
  }
  return closure
}
function multiply(...args) {
  return args.reduce((total, current) => total * current)
}
curriedMultiply = currying(multiply)
console.log(curriedMultiply(2)(3, 4)())

Этап 4

В приведенном выше коде оценка времени выполнения функции основана на том, переданы ли параметры.
Но чаще более разумным основанием является общее количество аргументов, которое может принять исходная функция.

имя функцииlengthСвойство — это количество аргументов, которые принимает функция. Например:

function test1(a, b) {}
function test2(...args){}
console.log(test1.length) // 2
console.log(test2.length) // 0

Перепишите это:

function currying(fn) {
  let args_arr = [], max_length = fn.length
  let closure = function (...args) {
    // 先把参数加进去
    args_arr = args_arr.concat(args)
    // 如果参数没满,返回闭包等待下一次调用
    if (args_arr.length < max_length) return closure
    // 传递完成,执行
    return fn(...args_arr)
  }
  return closure
}
function add(x, y, z) {
  return x + y + z
}
curriedAdd = currying(add)
console.log(curriedAdd(1, 2)(3))

Карри в Лодаше

Каррирование Lodash гораздо более гибкое, после повторной передачи можно поставить первое значение-заполнитель.
Вы можете обратиться к«Реализация метода карри lodash», здесь анализироваться не будут.

Ссылка на ссылку

Здоровяк, каррирование JavaScript, понял?
Карринг функций JS
Внедрение метода карри Лодаша