【问题标题】:Why do I get “`TypeError`: `flattenDeep(...)` is not iterable”, if I don’t use the initial value for `reduce`?如果我不使用 `reduce` 的初始值,为什么会得到“`TypeError`: `flattenDeep(...)` is not iterable”?
【发布时间】:2018-12-31 11:32:52
【问题描述】:

当我编写下面的函数时,它会抛出以下错误:

const flattenDeep = (arr) => Array.isArray(arr)
  ? arr.reduce( (a, b) => [...flattenDeep(a), ...flattenDeep(b)])
  : [arr]

const a=flattenDeep([1, [[2], [3, [4]], 5],[[[[[[[1]]]]]]]])
console.log(a);

当我改变它时,它就起作用了。为什么加上初始值[]后可以运行?

const flattenDeep = (arr) => Array.isArray(arr)
  ? arr.reduce( (a, b) => [...flattenDeep(a), ...flattenDeep(b)], [])
  : [arr]

const a=flattenDeep([1, [[2], [3, [4]], 5],[[[[[[[1]]]]]]]])
console.log(a)

这工作正常,并打印[1, 2, 3, 4, 5, 1]

【问题讨论】:

    标签: javascript arrays ecmascript-6 reduce flatten


    【解决方案1】:

    您收到此错误的原因是,在开始时,flattenDeep(b) 将使用b === [[2], [3, [4]], 5] 调用。反过来,这将调用 flattenDeep(a)a === [2]

    Array.isArray([2])true,所以[2].reduce((a, b) =>) 将被调用,没有初始值。 reduce 考虑到初始值(如果有),然后是所有其他数组元素,作为ab 的参数,其中a 累积返回值,b下一个值

    在具有单个值(加上开头的初始值)的数组上调用reduce 的结果是该单个值。换句话说,函数体 [...flattenDeep(a), ...flattenDeep(b)] 根本没有执行,也没有创建数组。只有数组的第一个元素 2 会立即返回。

    所以flattenDeep([2])2,这是不可迭代的。

    添加初始值[] 会导致reduce总是返回一个数组,即使它只是那个空数组。当然,数组始终是可迭代的。

    【讨论】:

      【解决方案2】:

      你应该在使用Array.reduce()时提供一个初始值

      语法

      arr.reduce(callback[, initialValue])
      

      参数

      initialValue(可选)

      用作回调第一次调用的第一个参数的值。如果未提供初始值,则将使用数组中的第一个元素。在没有初始值的空数组上调用 reduce() 是错误的。

      reduce() 的工作原理

      假设发生了以下reduce() 的使用:

      [0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
        return accumulator + currentValue;
      });
      

      回调会被调用四次,每次调用的参数和返回值如下:

      +--------------+--------------+---------------+--------------+-----------------+--------------+
      |   callback   |  accumulator |  currentValue | currentIndex |      array      | return value |
      +--------------+--------------+---------------+--------------+-----------------+--------------+
      | first call   |           0  |            1  |           1  | [0, 1, 2, 3, 4] |            1 |
      | second call  |           1  |            2  |           2  | [0, 1, 2, 3, 4] |            3 |
      | third call   |           3  |            3  |           3  | [0, 1, 2, 3, 4] |            6 |
      | fourth call  |           6  |            4  |           4  | [0, 1, 2, 3, 4] |           10 |
      +--------------+--------------+---------------+--------------+-----------------+--------------+
      

      reduce() 返回的值将是最后一次回调调用 (10) 的值。

      您还可以提供Arrow Function 来代替完整功能。下面的代码将产生与上面代码块中的代码相同的输出:

      [0, 1, 2, 3, 4].reduce( (accumulator, currentValue) => accumulator + currentValue );
      

      如果您要提供一个初始值作为 reduce() 的第二个参数,结果将如下所示:

      [0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {
          return accumulator + currentValue;
      }, 10);
      

      ..

      +--------------+-------------+--------------+--------------+-----------------+--------------+
      |   callback   | accumulator | currentValue | currentIndex |      array      | return value |
      +--------------+-------------+--------------+--------------+-----------------+--------------+
      | first call   |         10  |           0  |           0  | [0, 1, 2, 3, 4] |           10 |
      | second call  |         10  |           1  |           1  | [0, 1, 2, 3, 4] |           11 |
      | third call   |         11  |           2  |           2  | [0, 1, 2, 3, 4] |           13 |
      | fourth call  |         13  |           3  |           3  | [0, 1, 2, 3, 4] |           16 |
      | fifth call   |         16  |           4  |           4  | [0, 1, 2, 3, 4] |           20 |
      +--------------+-------------+--------------+--------------+-----------------+--------------+
      

      reduce() 在这种情况下返回的值是 20。

      希望这能解决您的问题

      【讨论】:

      • 问题是 为什么 OP 已经使用的初始值解决了问题。
      • You should supply an initial value when using Array.reduce(),你的话启发了我。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 2020-01-20
      • 2019-05-08
      • 1970-01-01
      相关资源
      最近更新 更多