Return 使用 reduce 时未定义

Return undefined when using reduce

考虑以下数组:

const books = [
  {
    id: 1,
    name: 'A song of ice and fire',
    genre: 'Fantasy',
    author: {
      name: 'George R. R. Martin',
      birthYear: 1948,
    },
    releaseYear: 1991,
  },
  {
    id: 2,
    name: 'The lord of the rings',
    genre: 'Fantasy',
    author: {
      name: 'J. R. R. Tolkien',
      birthYear: 1892,
    },
    releaseYear: 1954,
  },
  {
];

假设我想打印标题最长的书。以下作品:

const longestBook = () => {
  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book;
      }
      return accumulator;
    });
  return longestName
}

console.log(longestBook().name);

我的问题是,为什么我不能直接return book.name / accumulator.name 而不是只在调用函数时使用.name?如果我尝试这样做,结果是不确定的。

const longestBook = () => {
  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book.name;
      }
      return accumulator.name;
    });
  return longestName
}

console.log(longestBook());

如果累加器变为 .name 属性,它将是一个普通字符串,并且在下一次迭代中不再有 .name 属性 进行比较。

您需要通过提供初始值从一开始就与您的累加器类型保持一致。一个空字符串就足够了...

return books.reduce(
  (acc, { name }) => name.length > acc ? name : acc,  
  "" // initial value
);

使用 reduce,您将传递单个值 - 累加器 - 从上一次迭代到当前迭代。在 decently-structuredreduce 回调中,累加器通常应在整个循环中保持相同的形状,以便可以预测且一致地对其执行逻辑。

如果您尝试 return 仅 .name,则会出现问题:

  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book.name;
      }
      return accumulator.name;
    });

因为

  • 因为你没有提供初始值,第一次迭代的累加器将是第一本书object
  • 在第一次迭代中,您 return 来自第一本书对象或第二本书对象的 .name。名称是一个字符串,所以这导致累加器是第二次迭代的字符串
  • 在第二次迭代中,累加器现在是一个字符串 - 而不是书籍对象 - 因此 return accumulator.name 不会 return 任何东西。

您将累积一个字符串而不是一个对象,因此您的整个 reduce() 方法都需要面向此。

这也意味着您需要为 reduce() 提供初始值。默认情况下,它采用数组的第一个值,这是一个对象,而不是字符串。

const books = [{
  id: 1,
  name: 'A song of ice and fire',
  genre: 'Fantasy',
  author: {
    name: 'George R. R. Martin',
    birthYear: 1948,
  },
  releaseYear: 1991,
}, {
  id: 2,
  name: 'The lord of the rings',
  genre: 'Fantasy',
  author: {
    name: 'J. R. R. Tolkien',
    birthYear: 1892,
  },
  releaseYear: 1954,
}];


const longestBook = () => {
  const longestName = books.reduce((accumulator, { name }) => {
    if (name.length > accumulator.length) {
      return name;
    }
    return accumulator;
  }, '');
  return longestName;
}

console.log(longestBook());