ES6 .forEach方法不循环数组?

时间:2017-02-20 23:38:59

标签: javascript ecmascript-6

我的.forEach循环遇到了一些麻烦。这是我目前的代码:

let isPangram = (phrase) => {
  let alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
  alphabet.forEach(function(letter) {
    if (phrase.toLowerCase().includes(letter)) {
      alphabet.splice(alphabet.indexOf(letter), 1);
    }
    debugger;
  });
  if (alphabet.length === 0) {
    return true;
  }
  else if (alphabet.length > 0) {
    return false;
  }
};

当我使用debugger在控制台中运行此功能时,它似乎会跳过某些字母,例如bc。谁能告诉我这里发生了什么?

1 个答案:

答案 0 :(得分:1)

在使用.forEach()进行迭代时,不应该从数组中删除当前元素。当您使用.splice()删除时,它会删除一个元素,然后数组中的元素向下移动一个插槽,然后迭代的下一步将错过刚刚移入当前迭代槽的元素。

更安全的方法是使用传统的for循环并从头到尾迭代。然后,您对数组所做的任何更改都将超出您的迭代次数。当然,可能只有更好的整体方式来编写它而不需要拼接。就我个人而言,我可能会使用一个Set对象来跟踪所有使用过的字母,看看我最终是否会得到所有26个。

MDN page for .forEach() “如果在迭代过程中删除了已访问过的元素(例如使用shift()),则会跳过后面的元素 - 请参阅下面的示例。”

此外,forEach()不是ES6的新功能,自ES5以来一直存在。

这是使用某些ES6功能测试pangram的非删除方式:

const allCharsSet = new Set("abcdefghijklmnopqrstuvwxyz");

function isPangram(phrase) {
    let foundLetters = new Set();
    for (let ch of phrase) {
    	ch = ch.toLowerCase();
        if (allCharsSet.has(ch)) {
        	foundLetters.add(ch);
        }
    }
    return foundLetters.size === allCharsSet.size;
}

console.log(isPangram("The five boxing wizards jump quickly."));
console.log(isPangram("Many-wived Jack laughs at probes of sex quiz."));
console.log(isPangram("Playing jazz vibe chords quickly excites my wife."));
console.log(isPangram("some other phrase"));