Элемент "Распространение" магически превращает функции в "не функции",

Предположим, что у меня есть эта простая функция JavaScript:

function returnArray(){
    return [1, 2, 3];
}

Далее предположим, что я тогда скажу

var test = [0, ...returnArray()];

Вы ожидаете, что тест будет равен [0,1,2,3], и вы будете правы. Я пробовал это и, конечно же, работает.

Теперь у меня есть это упражнение, где я могу построить функцию double, которая принимает массив как параметр и возвращает другой массив, который содержит все исходные значения массива в два раза. Поэтому, если я называю double ([1,2,3]), я должен получить [2,4,6]. Ограничения упражнения состоят в том, что я должен использовать только деструктурирование массива, рекурсию и операторы rest/spread для создания моей функции. Никаких помощников массива не разрешено. Поэтому я придумал это:

function double(array){
  if (array.length===1) return 2*array[0];
  var [num, ...rest] = array;  
  if (rest.length!=0) return [2*num, ...double(rest)];  
}

Если я запустил эту функцию с любым массивом размером не менее двух, я получаю сообщение об ошибке, говорящее, что double не является функцией. Если я удаляю оператор... перед двойным, то магически двойной является функцией снова, за исключением того, что, конечно, результат двойного ([1,2,3]) равен [2, [4,6]], что не совсем так же, как [2,4,6].

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

EDIT: Спасибо всем, это была довольно глупая ошибка! Я должен был это увидеть. Я добавил комментарии к некоторым вашим ответам.

Ответы

Ответ 1

Это очень странное сообщение об ошибке, без вопросов, но главной проблемой является логическая ошибка в double: в двух ветвях кода вызов double приводит к неистребимому значению (в одном случае число, в другом undefined). Но вы всегда применяете к нему всплывающие обозначения. Так что это не удается в этих двух случаях. Случаи:

  • Вы возвращаете число, а не массив, в случае array.length === 1.
  • Вы ничего не возвращаете в случае, когда array.length не 1 и rest.length равно 0, поэтому результат вызова double в этом случае равен undefined.

Вы попадаете в случай, когда вы сначала пытаетесь распространить номер, например:

function a() {
  return 42;
}
const b = [...a()];

Ответ 2

Ваша логическая ошибка указана в комментариях и ответах, но позвольте мне указать на более чистый, более простой и менее склонный к ошибкам способ написать это, что больше соответствует основным принципам рекурсии.

function double([head, ...tail]) {
  if (head === undefined) return [];
  return [2*head, ...double(tail)];
}

Другими словами, существует только один "базовый случай", а именно пустой массив, который возвращает пустой массив. Все остальное - простая рекурсия.

Вы можете "функционализировать" это далее с помощью

function map(fn) {
  return function iter([head, ...tail]) {
    return head === undefined ? [] : [fn(head), ...iter(tail)];
  };
}

const double = map(x => 2*x);
console.log(double([1, 2, 3]));

Ответ 3

Просто небольшое изменение:

function double(array) {
  // note the return here is an array, not a number
  if (array.length === 1) return [2 * array[0]];

  var [num, ...rest] = array;
  if (rest.length) return [2 * num, ...double(rest)];
}

console.log(double([1, 2, 3, 4]));

Ответ 4

Вот ошибка, которую я получаю с помощью [email protected]

if (rest.length!=0) return [2*num, ...double(rest)];  
                                        ^

TypeError: double(...)[Symbol.iterator] is not a function
    at double (/home/henrique/labs/test.js:4:41)
    at double (/home/henrique/labs/test.js:4:41)
    at Object.<anonymous> (/home/henrique/labs/test.js:7:1)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:390:7)

Что, вероятно, означает, что результат оценки какого-либо вызова вашей функции не является итерируемым.

Ошибка здесь:

if (array.length===1) return 2*array[0];

Изменить на:

if (array.length===1) return [2*array[0]];

и он будет работать.