Элемент "Распространение" магически превращает функции в "не функции",
Предположим, что у меня есть эта простая функция 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]];
и он будет работать.