为了保证可读性, 本文采用意译而非直译. 另外, 本文版权归原作者所有, 翻译仅用于学习.
我保证这是一篇可以快速阅读并吸收的文章. 在过去的几个月里, 我检查的所有的 pull request 中, 都犯了这 4 个的错误. 我写这篇文章的另一个原因在于我自己也犯过这些错. 我们来看看如何正确地使用它们!
1. 不要使用 Array.indexOf, 使用 Array.includes
"如果你要在数组中查找元素, 使用 Array.indexOf!". 记得在我学习 JavaScript 课程时候, 有这样一句话. 这句话没错, 确实可以这么使用!
根据 MDN 文档:"Array.indexOf 会返回被查找元素第一个匹配的位置的下标." 因此, 如果后面需要用到这个索引, Array.indexOf 是一个很好的解法.
但是, 我们要解决的问题是: 查找数组中是否包含某个元素. 这是一个 Yes/No 的问题, 是一个返回布尔类型的真假问题. 因此, 我建议使用 Array.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
2. 不要使用 Array.filter, 使用 Array.find
Array.filter 是一个很有用的函数, 它返回一个满足过滤条件的新数组. 正如其名字表达的含义, 它是用来做过滤的.
但是, 如果我们知道我们要的结果只有一个元素的时候, 我就不建议使用它了. 比如, 如果我们的回调函数定义用一个唯一的 ID 来过滤, 那么结果必然唯一了. 在这个情况下, Array.filter 会返回只有一个元素的数组. 因为既然能通过一个特定的 ID 来查找, 我们已经确定只有一个元素了, 那么使用数组就没有意义.
另外, 我们再来聊聊性能问题. 为了返回所有匹配的元素, Array.filter 需要查找整个数组. 可以想象一下, 如果有上百个元素满足过滤条件, 那么返回的数组就很大.
为了避免这样的情况, 我建议使用 Array.find. 它仅仅返回第一个满足过滤条件的元素. 而且, Array.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' }
3. 不要使用 Array.find, 使用 Array.some
我承认我犯过很多次错误. 后来, 一个很要好的朋友让我去看看 MDN 的文档 https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Global_Objects/Array#Methods_2 , 说有更好的解决方案. 这个情况和刚刚提到的 Array.indexOf/Array.includes 很像.
在前面的例子中, 我们看到 Array.find 接受一个过滤函数, 返回满足的元素. 那么, 如果我们要查找一个数组是否包含某个元素的时候, Array.find 是否是最佳的方案呢? 可能不是, 因为它返回的是元素具体的值, 而不是布尔值.
我推荐大家使用 Array.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
4. 不要使用 Array.map 和 Array.filter 组合, 使用 Array.reduce
Array.reduce 有点难以理解! 但是, 如果我们每次在同时使用 Array.filter 和 Array.map 的时候, 你是否觉察到需要点东西, 对不?
我的意思是: 我们对整个数组循环了 2 遍. 第一次是过滤返回一个新的数组, 第二次通过 map 又构造一个新的数组. 我们使用了两个数组方法, 每一个方法都有各自的回调函数, 而且 Array.filter 返回的数组以后再也不会用到.
为了避免低效率, 我建议使用 Array.reduce. 同样的结果, 更优雅的代码! 请看下面的例子:
- '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'] }
- // ]
备注
malgosiastp https://medium.com/@malgosia.stepniak and David Piepgrass https://medium.com/@qwertie 在评论中提到: 在使用 Array.find 和 Array.includes 前请注意检查兼容性, 因为最新的 IE 不支持.
关于 Fundebug
Fundebug https://www.fundebg.com/ 专注于 JavaScript, 微信小程序, 微信小游戏, 支付宝小程序, React Native,Node.js 和 Java 实时 BUG 监控. 自从 2016 年双十一正式上线, Fundebug 累计处理了 6 亿 + 错误事件, 得到了 Google,360, 金山软件等众多知名用户的认可. 欢迎免费试用!
来源: http://www.qdfuns.com/article/40048/73420ed021a215034aee3b4e29c15a2a.html