是时候换个姿势使用 JavaScript 数组了

作者简介:
李中凯老师,8年前端开发,前端负责人,擅长JavaScript/Vue。
公众号:1024译站
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
主要分享:Vue.js, JavaScript,CSS


随着 ECMASCRIPT 6/7/8 的推进,越来越多的 JavaScript 新特性被主流浏览器支持。长期以来广大 JS 开发者习以为常的用法,也该考虑换换姿势了。今天就来聊聊数组的新用法,相信从此以后你的代码会清爽很多。

1. 用 Array.includes 替代 Array.indexOf

差不多从学会 JavaScript 开始,我们都是这样判断数组是否包含某个元素的:Array.indexOf(element) > -1。且不说语义上不够直观,在条件判断语句中经常会忘记加上>-1 从而导致 bug。试试Array新增的includes方法,它直接返回truefalse表示数组是否包含元素。这样是不是直观多了?

'use strict';const characters = [  '钢铁侠',  '黑寡妇',  '浩克',  '美国队长',  '浩克',  '雷神',
];console.log(characters.indexOf('浩克'));// 2console.log(characters.indexOf('蝙蝠侠'));// -1console.log(characters.includes('浩克'));// trueconsole.log(characters.includes('蝙蝠侠'));// false

2. 用 Array.find 替代 Array.filter

同样,为了在对象数组中查找符合条件的对象,以前的做法是用filter筛选,它会返回符合条件的数组。但我们的目的是查找具体的单个对象,所以使用find更合适:

'use strict';

const characters = [
  { id: 1, name: '钢铁侠' },
  { id: 2, name: '黑寡妇' },
  { id: 3, name: '美国队长' },
  { id: 4, name: '美国队长' },
];

function getCharacter(name) {
  return character => character.name === name;
}

console.log(characters.filter(getCharacter('美国队长')));
// [
//   { id: 3, name: '美国队长' },
//   { id: 4, name: '美国队长' },
// ]

console.log(characters.find(getCharacter('美国队长')));
// { id: 3, name: '美国队长' }

3. 用 Array.some 替代 Array.find

有时候我们需要判断对象数组中符合条件的对象是否存在,虽然用find也可以达到目的,但还是不够直接,最好能直接返回truefalseArray.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.reduce 替代 Array.filter 和 Array.map

Array.reduce这货看上去不那么好理解,但熟悉之后你会发现它非常好用。它实际上是一个叠加器,它遍历整个数组,把每个元素传入累加器函数执行一次,并把执行结果作为下一次迭代的输入参数。你可以在叠加器里做任何事,比如数字求和、数组和字符串拼接、对象属性操作等。

比如这样一个需求,在城市数组里筛选属于广东省的,然后给每个对象加上一个地区属性。以往的做法是先用filter筛选出结果数组,再用map构造新的对象数组。这样其实遍历了两次数组,性能不够好。使用Array.reduce可以实现一次遍历就完成了:

'use strict';

const cities= [
  { city: '广州市', province: '广东省' },
  { city: '深圳市', province: '广东省' },
  { city: '石家庄市', province: '河北省' },
];

console.log(
  cities
    .filter(city=> city.province=== '广东省')
    .map(city=> Object.assign({}, city, { region: '华南区' }))
);
// [
//   { city: '广州市', province: '广东省', region: '华南区' },
//   { city: '深圳市', province: '广东省', region: '华南区' }
// ]

console.log(
  cities
    .reduce((acc, city) => {
      return city.province=== '广东省'
        ? acc.concat(Object.assign({}, city, { region: '华南区' }))
        : acc;
    }, [])
)
// [
//   { city: '广州市', province: '广东省', region: '华南区' },
//   { city: '深圳市', province: '广东省', region: '华南区' }
// ]

总结

新的语言标准通常会提供更加便捷和高性能的操作来实现某项功能。虽然也可以通过旧的 API 绕弯子实现,但无论从可读性还是性能上来说,简单直接的 API 无疑更受欢迎。

本文已经获得李中凯老师授权转发,其他人若有兴趣转载,请直接联系作者授权。

作者简介:
李中凯老师,8年前端开发,前端负责人,擅长JavaScript/Vue。
公众号:1024译站
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
主要分享:Vue.js, JavaScript,CSS

发布了775 篇原创文章 · 获赞 1092 · 访问量 63万+

猜你喜欢

转载自blog.csdn.net/jnshu_it/article/details/104803865