是时候换个姿势使用 JavaScript 数组了
随着 ECMASCRIPT 6/7/8 的推进,越来越多的 JavaScript 新特性被主流浏览器支持。长期以来广大 JS 开发者习以为常的用法,也该考虑换换姿势了。今天就来聊聊数组的新用法,相信从此以后你的代码会清爽很多。
1. 用 Array.includes 替代 Array.indexOf
差不多从学会 JavaScript 开始,我们都是这样判断数组是否包含某个元素的:Array.indexOf(element) > -1
。且不说语义上不够直观,在条件判断语句中经常会忘记加上>-1
从而导致 bug。试试Array新增的includes
方法,它直接返回true
或false
表示数组是否包含元素。这样是不是直观多了?
'use strict';
const characters = [
'钢铁侠',
'黑寡妇',
'浩克',
'美国队长',
'浩克',
'雷神',
];
console.log(characters.indexOf('浩克'));
// 2
console.log(characters.indexOf('蝙蝠侠'));
// -1
console.log(characters.includes('浩克'));
// true
console.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
也可以达到目的,但还是不够直接,最好能直接返回true
或false
。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.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 无疑更受欢迎。
如果你觉得文章有用,可以关注我的微信公众号:1024译站,下一篇更精彩!
微信公众号:1024译站