扩展元素神奇地将函数变成"非函数"



假设我有这个简单的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)。但是您总是对其应用传播表示法。所以这在这两种情况下都失败了。 这些案例是:

  1. array.length === 1情况下,您只返回数字,而不是数组。
  2. 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]];

它会起作用。

最新更新