Введение в ООП

Здравствуйте! Перешёл к интересному заданию. Ниже, я предоставлю само задание и свой код и попробую объяснить, что я делаю. Я очень прошу вас поправить меня там, где ошибусь и направить на дальнейшее решение:

Задание

magic.js

Реализуйте и экспортируйте по умолчанию функцию, которая работает следующим образом:

  • Принимает на вход любое число аргументов и возвращает функцию, которая, в свою очередь, принимает на вход любое количество аргументов и так до бесконечности (привет, рекурсия ;)).
  • Результат вызова этой функции при проверке на равенство должен быть равен сумме всех аргументов всех подфункций.
magic() == 0; // true
magic(5, 2, -8) == -1; // true
magic(1, 2)(3, 4, 5)(6)(7, 10) == 38; // true
magic(4, 8, 1, -1, -8)(3)(-3)(7, 2) == 13; // true

Подсказки

  • Функции это объекты

Мой код:

const magic = (...arg) => {
   const arr = [...arg];
   magic.prototype.getResult = function(){
     if(result != underfined){
       return this.result;
     }else{
       return 0;
     }  
    }

 const result = arr.reduce((total, nextEl) => total + nextEl, magic.getResult);
 magic.prototype.setResult = function(result){
   this.result = result;
 }
 return make; 
}

Как я понимаю решение этой задачи…
Как видно из теории, нам необходимо возвращать функцию с новыми параметрами и плюсовать их с уже имеющимся результатом от предыдущего вызова.
Для этого, я решил использовать reduce, который благодаря своему второму параметру(здесь это magic.getResult) позволяет начинать суммировать с этой суммы. То есть, если мы указываем второй параметр, то в параметр total попадает значение этого второго параметра reduce.
Прототипы, я хочу использовать для того, чтобы записывать и вытаскивать уже имеющуюся сумму, которая находится в result. Но здесь я понимаю, что использую их не правильно.
Во первых, не понимаю, можно ли их использовать внутри функции, в которую и записываешь прототип. Или их обязательно надо вытаскивать наружу?
Во вторых, можно ли использовать саму функцию для записи прототипа, да ещё и записывать и вытаскивать значение при помощи this Функция конечно объект, но правильно ли так делать?
В третьих, что возвращать из функции magic?

Используй просто свойство в функции. Прототипы идиоматически нужны только для наследования и описания классов.

Не правильно. Это как набивание меча на ноге: интересное упражнение но во время матча никто таким не занимается.

Вот это хороший вопрос. Это должно быть нечто что

  1. Функция (потому что это нужно мочь продолжить вызывать)
  2. Эта функция должна знать про предыдущие вызовы (можно в magic конструкировать функцию (f1), возвращать ее (f1), а при последующих ее (f1) вызовах возвращать ее (f1) саму.
  3. magic() == 0; // true фишка сравнения (обрати внимание что оно нестрогое) в том что если с разных сторон неравенства стоят несовместимые типы, то интерпретатор пытается привести типы. Один из подкапотных шагов который он делает - вызов метода valueOf у несоответствующего типа. Мы уже определили что результат magic - должна быть функция. Если ей сделать метод valueOf который возвращает число, то он будет вызываться при нестрогом сравнении и поведение сравнении будет таким как ожидается.

не совсем понятно, что нужно делать…

Я описал не шаги, а какие ограничения и требования у решения. Шаги придумывать тебе.

Могу дать готовый ответ

как использовать свойства функции? Что ты имеешь ввиду?

function lol() {
    return 100500
}
lol.ppp = true
console.log(lol(), lol.ppp)// 100500, true

да, но я не смогу в свойство записать это:

function(){
     if(result != underfined){
       return this.result;
     }else{
       return 0;
     }  
    }

Верно. this тут не при чем. Тебе нужен референс (ссылка) на функцию (иными словами переменная с функцией)

function magic() {
    const fn = () => {}
    fn.res = 100500
    return fn
}

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

function magic() {
    let res = []
    const fn = () => { // use res }
    return fn
}

если бы всё было так просто) В обсуждениях к задачи прочитал, что те кто использовали в задаче глобальную переменную - не проходили второй тест. Никаких записей в глобальную переменную не должно быть. Оно и верно! В реальном коде этого нужно избегать

Ни в одном из моих примеров я не использую глобальную переменную:

Ниже fn создается при первом вызове magic. Новый вызов - новая fn, соответственно .res у них будет разный.

function magic() {
    const fn = () => {}
    fn.res = 100500
    return fn
}

Тут переменная res в замыкании и создается при первом вызове magic. Механика как в коде выше.

function magic() {
    let res = []
    const fn = () => { // use res }
    return fn
}

Хорошо, а идея моя имеет право на жизнь? Логически я правильно замыслил со вторым параметром в reduce?

а при новом вызове magic, ты не потеряешь значение в res?

Стратегически. Нет.

Эта механика как раз с “глобальной” переменной.

При такой последовательности вызова magic будет содержать предыдущие состояния которые повлияют на результат во второй строчке.

magic() == 0; // true
magic(5, 2, -8) == -1; // true

Записывать в prototype методы неверно идеологически.


Тактически тоже много проблем.

magic.getResult - это должен быть вызов.
this.result = result; - this не причем так как ты не работаешь с инстансами классов
magic.prototype.getResult запись в prototype не даст возможность вызывать код так: magic.getResult.
magic.prototype.setResult - лишний код, метод не нужен ты можешь сразу записать результат куда нужно.

Нет, я про reduce со вторым параметром имел ввиду. Правильно ли пошёл в этом смысле… Про prototype я уже понял

const magic = (...arg) => {
   const arr = [...arg];
   
 const result = arr.reduce((total, nextEl) => total + nextEl, boxCounter); // как-то надо сохранять boxCounter
 
 return ...; 
}

Стартовать reduce с предыдущего значения? Да.

Дмитрий, нужна небольшая помощь. Решил написать функцию magic c рекурсией, используя внутреннюю функцию для вызова. Но у меня падает с ошибкой… Не могу понять, в чём она и как исправить?

const magic = function(...args){
  const sum = 0;
  const v = 0;
  const result = 0;
  const arr = [...args];

 function innerMagic(mySum, myV){
    const sumOf = mySum + myV;
    return sumOf;
  }
  let finish = arr.reduce(innerMagic(sum, v), result);
  return finish;
}

console.log(magic(5, 2, -8) == -1); // true

Вижу вот эту ошибку

TypeError: innerMagic(...) is not a function

Ее суть в том что результат вызова innerMagic(...) это не функция, а этот результат передается аргументом там где ожидается функция.

У меня ошибка следующая:

TypeError: 0 is not a function
    at Array.reduce
    at magic

не загружается картинка

Тебе не нужно разбираться с нулем. Потому что проблема в другом месте. Проблема описана в моем предыдущем комментарии Введение в ООП