Node.js:将forEach()与早期回报结合在一起

时间:2018-11-25 10:22:54

标签: node.js short-circuiting early-return

我的问题

ESLint airbnb策略不允许for...of循环迭代,而更喜欢forEach((element) => { code });。但是,该循环的内部返回被吞噬了-它们被视为匿名函数的returns而不是包含该循环的函数。

代码

原始

有效,但中断eslint-config-airbnb

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator1() {
  const wordlist = [];
  for (const word of words) {
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  }
  return wordlist;
}

console.log(NestedIterator1());

替代1:迭代数组索引

有效,但是样式已过时,我必须通过索引手动分配值。

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;


function NestedIterator2() {
  const wordlist = [];
  for (let i = 0; i < words.length; i += 1) {
    const word = words[i];
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  }
  return wordlist;
}


console.log(NestedIterator2());

替代2:使用forEach

遵循样式指南,但不起作用-内部返回被视为来自匿名函数而不是NestedIterator3的返回。

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator3() {
  const wordlist = [];
  words.forEach((word) => {
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  });
  return wordlist;
}

console.log(NestedIterator3());

我的问题

函数如何在允许早期返回并避免索引和for..of迭代的同时遍历数组?

1 个答案:

答案 0 :(得分:3)

一个选择是使用reduce,这非常灵活,可以在许多其他迭代方法不够用的情况下使用-如果累加器的长度为push,则只能使用MAX_WORDS小于单词长度的const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey']; const MIN_WORD_SIZE = 4; const MAX_WORDS = 3; function NestedIterator3() { return words.reduce((wordlist, word) => { if (wordlist.length < MAX_WORDS && word.length >= MIN_WORD_SIZE) { wordlist.push(word); } return wordlist; }, []); } console.log(NestedIterator3());

.some

仍然,上述方法确实遍历所有索引-实际上并没有尽早返回,只要满足了最终条件,它就不会在以后的迭代中做任何事情。如果您想真正脱离迭代器,可以使用const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey']; const MIN_WORD_SIZE = 4; const MAX_WORDS = 3; function NestedIterator3() { const wordlist = []; words.some((word) => { if (word.length >= MIN_WORD_SIZE) { wordlist.push(word); } return wordlist.length === MAX_WORDS; }, []); return wordlist; } console.log(NestedIterator3());来代替它,尽管它甚至更不纯净,并且IMO的代码意图不太明确:

filter

对于这个特定示例,您还可以使用slice后跟const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey']; const MIN_WORD_SIZE = 4; const MAX_WORDS = 3; function NestedIterator3() { return words .filter(word => word.length >= MIN_WORD_SIZE) .slice(0, MAX_WORDS) } console.log(NestedIterator3());

.filter

看起来确实优雅得多,但是reduce必须首先遍历数组中的所有项目,因此与static_cast有相同的问题(没有短路发生)-另外,这两种链接方法仅表示可能要使数组迭代短路的情况的子集。