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

时间:2017-05-19 13:42:39

标签: javascript arrays recursion

假设我有这个简单的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不是函数。如果我在double之前删除了...运算符,那么神奇的double再次是一个函数,除了当然double([1,2,3])的结果是[2,[4,6]],这是不完全的与[2,4,6]相同。

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

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

4 个答案:

答案 0 :(得分:24)

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

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]));

答案 1 :(得分:10)

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

  1. 您只在array.length === 1案例中返回数字,而不是数组。
  2. array.length不是1且rest.length为0的情况下,您没有返回任何内容,因此在这种情况下调用double的结果为{{1} }。
  3. 您正试图先尝试传播号码,例如:

    
    
    undefined
    
    
    

    对于#1,您应该返回一个包含一个条目的数组。对于#2,您应该返回function a() { return 42; } const b = [...a()];。所以最小的变化版本是:

    
    
    []
    
    
    

答案 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

答案 3 :(得分:1)

以下是使用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]];

它会起作用。