假设我有这个简单的JavaScript函数:
function returnArray(){
return [1, 2, 3];
}
进一步假设我然后说
var test = [0, ...returnArray()];
你会期望测试等于 [0,1,2,3],你是对的。我试过了,当然有效。
现在我有了这个练习,我假设构建一个名为 double 的函数,该函数将数组作为参数并返回另一个数组,该数组包含所有原始数组的值加倍。因此,如果我调用double([1,2,3]),我应该得到[2,4,6]。练习的约束是我必须仅使用数组解构、递归和其余/扩展运算符来构建我的函数。不允许使用数组帮助程序。所以我想出了这个:
function double(array){
if (array.length===1) return 2*array[0];
var [num, ...rest] = array;
if (rest.length!=0) return [2*num, ...double(rest)];
}
如果我使用大小至少为 2 的任何数组运行此函数,则会收到一条错误消息,指出 double 不是函数。如果我删除...双精度运算之前,神奇的双精度又是一个函数,当然双精度的结果是 [2,[4,6]],这与 [2,4,6] 并不完全相同。
我的第一个想法是,也许出于某种奇怪的原因,你不能使用......在一个函数前面,即使函数返回一个数组,所以我用上面的 returnArray() 函数测试了这个假设,发现它工作得很好。我不知道为什么它在练习中崩溃了。我只能猜测递归可能与它有关,但我不知道为什么会这样。谁能指出我的代码出了什么问题?
编辑:谢谢大家,这是一个非常愚蠢的错误!我应该看到的。我在你的一些答案中添加了评论。
你的逻辑错误已经在评论和答案中指出了,但让我指出一种更干净、更简单、更不容易出错的写法,它更符合递归的基本原则。
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]));
这是一个非常奇怪的错误消息,毫无疑问,但主要问题是double
中的逻辑错误: 在代码的两个分支中,调用double
会产生一个不可迭代的值(在一种情况下是数字,在另一种情况下是undefined
)。但是您总是对其应用传播表示法。所以这在这两种情况下都失败了。 这些案例是:
- 在
array.length === 1
情况下,您只返回数字,而不是数组。 - 在
array.length
不是 1 而rest.length
不是 0 的情况下,您不会返回任何内容,因此在这种情况下调用double
的结果是undefined
。
你遇到了你试图先传播一个数字的情况,就像这样:
function a() {
return 42;
}
const b = [...a()];
对于 #1,您应该返回一个带有一个条目的数组。对于#2,您应该返回[]
。因此,最小更改版本为:
function double(array) {
if (array.length === 1) {
return [2*array[0]];
// ^−−−−−−−−−−^−−−−−−−−−−− note
}
var [num, ...rest] = array;
if (rest.length > 0) {
return [2*num, ...double(rest)];
}
return []; // <−−−−−−−−−−−−−−−−− note
}
console.log(double([1,2,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]));
您返回了一个数字,解构一个数字会给您留下错误。
...5 // throws SyntaxError
这是我使用node@6.10.3
时遇到的错误
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]];
它会起作用。