Каррирование с использование apply/bind/call

Помогите пожалуйста пересмотрел уже ролики по каррированию, apply/bind/call, замыканиям. Вроде все понятно но как решить задачу никак не могу додуматься.

Нужно при помощи apply/bind/call написать функцию, которая оборачивает другую функцию так, чтобы результатом была тоже функция, но еще могла принимать заданное кол-во аргументов. Функция принимает на вход другую функцию и число аргументов которое необходимо собрать чтобы передать в функцию которая была передана первым аргументом.

function watchArgs(fn, argumentsLength) {
  // Реализовать данную функцию
}

function test1(a, b, c) {
  return a + b + c;
}
function test2(a, b, c, d) {
  return a + b + c + d;
}

let result;

const t1 = watchArgs(test1, 3);
result = t1(); // все еще функция, необходимо учитывать если аргументы не были переданы
result = t1(1, 2); // все еще функция
result = t1(3); // 6 - результат выполнения функции test1 с аргументами 1, 2 и 3

const t2 = watchArgs(test2, 4);
result = t2(1);
result = t2(1);
result = t2(1, 1); // 4
result = t2(5); // 4

Ответы (1 шт):

Автор решения: OPTIMUS PRIME

Использован только fn.apply(контекст, массив) — Он нужен, чтобы вызвать функцию, передав ей элементы массива или другого итерируемого объекта как аргументы.

function watchArgs(fn, length) {
  let args_cache = []; // Хранилище переданных аргументов при всех вызовах.

  return function _self() {
    if (args_cache.length == length) {
      // Набрано достаточно аргументов?
      // Вызов исходной функции, и на выход.
      return fn.apply(null, args_cache);
    }

    for (let i = 0; i < arguments.length; i++) {
      args_cache.push(arguments[i]);

      if (args_cache.length == length) {
        return fn.apply(null, args_cache);
      }
    }

    return _self; // Аргументов не хватает, возвращает саму себя.
  }
}

/***/
function test1(a, b, c) {
  return a + b + c;
}

function test2(a, b, c, d) {
  return a + b + c + d;
}

let result;

const t1 = watchArgs(test1, 3);
result = t1();
result = t1(1, 2);
console.log(result = t1(3));

const t2 = watchArgs(test2, 4);
result = t2(1);
result = t2(1);
console.log(result = t2(1, 1)); // 4
console.log(result = t2(5)); // 4

arguments, а заодно и apply (т.к. контекст не сохрняется), можно заменить на ... ( spread )

→ Ссылка