我保证这篇文章简短而切题。在过去的几个月里,我注意到在我审查的拉取请求中经常出现四个错误(关于数组的使用)。此外,我自己也犯了这些错误,因此才有了这篇文章。让我们一起学习,确保我们以后能正确使用数组方法!使用Array.includes而不是Array.indexOf“如果您需要在数组中查找元素,请使用Array.indexOf。”我记得在我的JavaScript类中有类似的内容。毫无疑问,这是绝对正确的!在MDN文档中,Array.indexOf的描述是:返回给定元素在数组中的第一个索引,如果不存在则返回-1。因此,如果您稍后需要在代码中使用索引(对于给定元素),那么Array.indexOf是显而易见的选择。但是,如果我们只需要知道给定元素是否包含在数组中怎么办?这意味着它只是一个是或否的区别,一个布尔问题。对于这种情况,我建议使用直接返回布尔值的Array.includes。'usestrict';constcharacters=['ironman','black_widow','hulk','captain_america','hulk','thor',];console.log(characters.indexOf('hulk'));//2console.log(characters.indexOf('batman'));//-1console.log(characters.includes('hulk'));//trueconsole.log(characters.includes('batman'));//假用Array.find替换Array.filterArray.filter是一个非常有用的方法。它通过回调函数过滤原始数组,并将过滤后的项目作为新数组返回。顾名思义,我们使用这种方法进行过滤,并且(通常)得到一个长度更短的新数组。但是,如果您知道通过回调函数过滤后只剩下一项,我不建议使用Array.filter。例如:使用等于一个唯一ID作为过滤条件来过滤一个数组。在此示例中,Array.filter返回一个只有一项的新数组。但是,由于我们只是试图获取具有特定ID的项目,因此这个新数组是无用的。让我们讨论性能。Array.filter为了得到所有符合回调函数过滤条件的项,必须遍历整个数组。如果原数组有几万条,回调函数需要执行多次。为了避免这些情况,我推荐使用Array.find。它需要像Array.filter这样的回调函数,(但只返回)满足条件的***项。当找到第一个符合回调函数过滤条件的元素时,立即停止向下查找。不再遍历整个数组。'usestrict';constcharacters=[{id:1,name:'ironman'},{id:2,name:'black_widow'},{id:3,name:'captain_america'},{id:4,name:'美国队长'},];functiongetCharacter(name){returncharacter=>character.name===name;}console.log(characters.filter(getCharacter('captain_america')));//[//{id:3,name:'captain_america'},//{id:4,name:'captain_america'},//]console.log(characters.find(getCharacter('captain_america')));//{id:3,name:'captain_america'}使用Array.some而不是Array.find我承认我经常犯这个错误。后来有朋友建议我去看看MDN文档,看看有没有更好的方法。事实上(这个错误)与上面的Array.indexOf/Array.includes示例非常相似。在上面的示例中,我们知道Array.find将回调函数作为参数并返回第一个(合格的)元素。但是,当我们需要知道一个元素是否存在于数组中时,Array.find是最好的选择吗?不一定,因为它返回一个元素,而不是布尔值。在下面的示例中,我建议使用Array.some,它会返回您需要的布尔值。'usestrict';constcharacters=[{id:1,name:'ironman',env:'marvel'},{id:2,name:'black_widow',env:'marvel'},{id:3,name:'wonder_woman',env:'dc_comics'},];functionhasCharacterFrom(env){returncharacter=>character.env===env;}console.log(characters.find(hasCharacterFrom('marvel')));//{id:1,name:'ironman',env:'marvel'}console.log(characters.some(hasCharacterFrom('marvel')));//true译者注:添加Array.some和Array.includes的使用区别。两者都返回一个布尔值,表示数组中是否存在某一项,找到对应项后停止遍历数组。不同之处在于Array.some的参数是一个回调函数,而Array.includes的参数是一个值(两者都与第二个可选参数无关)。假设你想知道数组中是否存在值为value的item,可以写代码:[].includes(value),也可以将item=>item===value作为回调函数传递给Array.some。Array.includes更易于使用,而Array.some更具操作性。使用Array.reduce代替Array.filter结合Array.map实际上,Array.reduce并不容易理解。但是,如果我们先使用Array.filter过滤原始数组,然后调用Array.map(在结果上)(以获取新数组)。这似乎是个问题,我们是不是忽略了什么?问题是:我们遍历数组两次。第一次是对原数组进行过滤,得到一个长度更短的新数组,第二次遍历(译者注:指Array.map)是对Array.filter返回的新数组进行处理,重新创建一个新数组大批!为了获得最终结果,我们结合了两种数组方法。每个方法都有自己的回调函数,Array.map使用的临时数组由Array.filter提供,(一般情况下)不能重复使用。为了避免这种低效的情况,我的建议是使用Array.reduce。同样的结果,更好的代码!Array.reduce允许您将过滤和处理的项目放入累加器中。累加器可以是要递增的数字、要填充的对象、要连接的字符串或数组等。在上面的示例中我们使用了Array.map,建议(但更多)使用Array.reduce和累加器是要连接的数组。在下面的示例中,根据变量env的值,我们将其添加到累加器或保持累加器不变(即什么都不做)。'usestrict';constcharacters=[{name:'ironman',env:'marvel'},{name:'black_widow',env:'marvel'},{name:'wonder_woman',env:'dc_comics'},];console.log(characters.filter(character=>character.env==='marvel').map(character=>Object.assign({},character,{alsoSeenIn:['复仇者联盟']})));//[//{name:'ironman',env:'marvel',alsoSeenIn:['Avengers']},//{name:'black_widow',env:'marvel',alsoSeenIn:['Avengers']}//]console.log(characters.reduce((acc,character)=>{returncharacter.env==='marvel'?acc.concat(Object.assign({},character,{alsoSeenIn:['复仇者联盟']})):acc;},[]))//[//{name:'ironman',env:'marvel',alsoSeenIn:['Avengers']},//{name:'black_widow',env:'marvel',alsoSeenIn:['Avengers']}//]本文就这些!希望这对你有帮助。如果您对本文或要讨论的示例(数组方法的用法)有任何意见,请在评论中告诉我。如果你觉得这篇文章不错,请给我一个赞👏(译者注:我对着灯发誓,这是原文,不是译者作弊!)分享给更多的朋友。谢谢阅读!PS:你可以在推特上关注我。
