Spread元素神奇地将函数转换为'not functions'

Nic*_*ola 15 javascript arrays recursion

假设我有这个简单的JavaScript函数:

function returnArray(){
    return [1, 2, 3];
}
Run Code Online (Sandbox Code Playgroud)

进一步假设我接着说

var test = [0, ...returnArray()];
Run Code Online (Sandbox Code Playgroud)

你期望测试等于[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)];  
}
Run Code Online (Sandbox Code Playgroud)

如果我使用任何大小至少为2的数组运行此函数,我会收到一条错误消息,指出double不是函数.如果我在double之前删除了...运算符,那么神奇的double再次是一个函数,除了当然double([1,2,3])的结果是[2,[4,6]],这是不完全的与[2,4,6]相同.

我的第一个想法是,也许,出于一些奇怪的原因,你不能在函数前使用...,即使函数返回一个数组,所以我用上面的returnArray()函数测试了这个假设,并找到了它工作得很好.我不知道它为什么会在练习中崩溃.我只能猜测递归可能与它有关,但我不知道为什么它会如此.任何人都可以指出我的代码有什么问题吗?

编辑:谢谢大家,这是一个非常愚蠢的错误!我应该看到它.我在你的一些答案中添加了评论.

小智 24

您的逻辑错误已经在评论和答案中指出,但是让我指出一种更简洁,更容易出错的方式来编写它,这更符合递归的基本原则.

function double([head, ...tail]) {
  if (head === undefined) return [];
  return [2*head, ...double(tail)];
}
Run Code Online (Sandbox Code Playgroud)

换句话说,只有一个"基本情况",即空数组,它返回一个空数组.其他一切都是简单的递归.

你可以进一步"功能化"这个

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]));
Run Code Online (Sandbox Code Playgroud)


T.J*_*der 9

这是一个非常奇怪的错误消息,毫无疑问,但主要问题是逻辑错误double:在代码的两个分支中,调用double不可迭代的值(在一种情况下是一个数字,在另一个中undefined).但是你总是将扩散符号应用于它.因此在这两种情况下失败了.案例是:

  1. 在这种array.length === 1情况下,您只返回数字,而不是数组.
  2. 如果array.length不是1并且rest.length为0,则不返回任何内容,因此double在这种情况下调用的结果是undefined.

您正试图先尝试传播一个数字,如下所示:

function a() {
  return 42;
}
const b = [...a()];
Run Code Online (Sandbox Code Playgroud)

对于#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]));
Run Code Online (Sandbox Code Playgroud)

  • @Nicola传递空数组时. (3认同)