有效使用JavaScript中的数组方法

该材料的作者(我们今天将其翻译发表)说,在过去的几个月中,当检查请求请求时,他不断遇到与在JavaScript中不合理使用数组方法相关的四个缺点。 为了减少以前在他的程序中出现的这种代码缺陷,他写了这篇文章。



用include()替换indexOf()


“如果要在数组中查找内容,请使用indexOf()方法。” 在学习JavaScript的其中一门课程中,我遇到了这样的建议。 这个建议是很正常的,没什么不好说的。

在MDN上,您可以发现indexOf()方法返回第一个索引,通过该索引可以在数组中找到某个元素。 这意味着,如果我们计划在程序中使用此索引,则indexof()方法非常适合在数组中查找元素。

但是,如果我们只需要找出数组中是否存在某个元素怎么办? 也就是说,如果该元素在数组中,则我们对它的索引不感兴趣,而对它的存在或不存在的事实不感兴趣。 通过这种方法,我们对返回truefalse的命令非常满意。 在这种情况下,建议不要使用indexOf()方法,而是使用includes()方法,该方法返回一个布尔值。 考虑一个例子:

 'use strict'; const characters = [ 'ironman', 'black_widow', 'hulk', 'captain_america', 'hulk', 'thor', ]; console.log(characters.indexOf('hulk')); // 2 console.log(characters.indexOf('batman')); // -1 console.log(characters.includes('hulk')); // true console.log(characters.includes('batman')); // false 

使用find()方法代替filter()方法


filter()方法是一个非常有用的工具。 它在一个数组的基础上创建另一个包含与指定条件匹配的原始数组元素的数组。 从该方法的名称可以理解,它旨在过滤数组,在此期间通常会获得比原始数组短的数组。

如果我们知道对数组进行过滤后会剩下一个元素怎么办? 例如,当您尝试基于某些唯一标识符过滤数组元素时,可能会发生这种情况。 在这种情况下,我不建议您使用filter()方法,因为它形成的数组将仅包含一个元素。 如果我们对具有唯一值的数组元素感兴趣,那么我们将使用单个值,并且不需要数组来表示这样的值。

如果我们谈论filter()方法的性能,那么事实证明,为了形成与调用时指定的条件相对应的元素列表,它必须查看整个数组。 此外,想象一下数组中有数百个满足给定条件的元素。 这将导致结果数组很大。

为了避免陷入这种情况,我建议使用find()方法。 调用该方法时,它将接收描述条件的回调,这与用于filter()方法的回调非常相似,但是find()方法仅返回与该条件匹配的第一个元素。 同时,此方法在找到这样的元素后立即停止工作。 结果,他不必浏览整个阵列。

 'use strict'; const characters = [ { id: 1, name: 'ironman' }, { id: 2, name: 'black_widow' }, { id: 3, name: 'captain_america' }, { id: 4, name: 'captain_america' }, ]; function getCharacter(name) { return character => 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' } 

用some()方法代替find()方法


我必须承认,我们现在将讨论的疏忽,我已经承诺了很多次。 然后他们建议我看一下MDN ,看看如何改进我的非理性做法。 简而言之,这与我们在谈论indexOf()includes()方法时所看到的非常相似。

在上述情况下,我们看到find()方法作为参数接受了回调并返回了数组元素。 如果我们需要找出数组是否包含某个值,可以将find()方法称为最成功的解决方案吗? 也许不是,因为此方法返回数组元素的值,而不是布尔值。

在这种情况下,我建议使用some()方法,该方法返回一个布尔值。

 'use strict'; const characters = [ { id: 1, name: 'ironman', env: 'marvel' }, { id: 2, name: 'black_widow', env: 'marvel' }, { id: 3, name: 'wonder_woman', env: 'dc_comics' }, ]; function hasCharacterFrom(env) { return character => character.env === env; } console.log(characters.find(hasCharacterFrom('marvel'))); // { id: 1, name: 'ironman', env: 'marvel' } console.log(characters.some(hasCharacterFrom('marvel'))); // true 

使用reduce()方法,而不是filter()和map()方法的组合


值得一提的是, reduce()方法不能归类为易于理解的方法。 但是,如果可以用两个步骤来完成它,同时使用filter()map()方法组合在一个链中,那么似乎这种方法是错误的。

我说用这种方法,您必须两次查看数组。 由filter()方法执行的第一遍,涉及查看整个数组并创建一个新的,经过过滤的数组。 在第二次通过map()方法执行之后,再次创建一个新数组,其中包含对运行filter()方法后获得的数组元素进行转换的结果。 结果,为了到达完成的阵列,使用了两种方法。 每个方法都有自己的回调,并且在使用filter()方法执行此类操作期间,将创建一个我们无法再使用的数组。

为了减轻使用两种方法创建的系统的负担并提高程序的生产率,在这种情况下,我建议使用reduce()方法。 结果将是相同的,但是代码会更好。 这种方法使您可以过滤我们感兴趣的元素并将其添加到电池中。 电池可以是一个数字变量,例如存储数组元素的总和,它可以是对象,字符串或数组,我们可以在其中累积所需的元素。

在我们的例子中,由于我们正在谈论使用map()方法,因此建议使用将array作为累加器的reduce()方法。 在下面的示例中,我们通过env字段的值过滤作为对象的数组元素,并执行其转换。

 'use strict'; const characters = [ { 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: ['Avengers'] })) ); // [ //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] }, //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] } // ] console.log( characters   .reduce((acc, character) => {     return character.env === 'marvel'       ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))       : acc;   }, []) ) // [ //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] }, //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] } // ] 

总结


在本文中,我们研究了有效使用数组方法解决各种问题的一些方法。 我们认为,本文作者提出的建议所基于的思想可以在其他情况下帮助改进JS代码。

亲爱的读者们! 您是否遇到过JavaScript机制分配错误的示例?

Source: https://habr.com/ru/post/zh-CN422091/


All Articles