const users = [ { id: 'af35', name: 'john' }, { id: '6gbe', name: 'mary' }, { id: '932j', name: 'gary' }, ] const user = users.findIndex(user => user.id === '6gbe') console.log(user) // 1
你或许认为 findIndex 跟 indexOf 是相同的。额……不完全是。indexOf 的第一个元素是基本值(布尔,数字,字符串,null,undefined或者一个 symbol)而findIndex的第一个元素是一个回调方法。
所以当你需要搜索在数组中的一个元素的基本值时,使用 indexOf。如果有更复杂的元素,比如object,使用 findIndex。
slice
当你需要取出或者复制数组的一部分,可以使用 slice。但是注意,像展开操作符一样, slice 返回部分的浅拷贝!
const numbers = [1, 2, 3, 4, 5] const copy = numbers.slice()
我在文章的开始谈到,循环是没有什么用的。来用一个例子说明你如何摆脱它。
假设你想去从 API 中去除一定量的聊天记录里,然后展示它们中的 5 条。有两种方式实现:一种是循环,另一种是 slice。
// 传统方式 // 用循环来决定消息的数量 const nbMessages = messages.length < 5 ? messages.length : 5 let messagesToShow = [] for (let i = 0; i < nbMessages; i++) { messagesToShow.push(posts[i]) } // 假设 arr 少于 5 个元素 // slice 将会返回原数组的整个浅拷贝 const messagesToShow = messages.slice(0, 5)
some
如果你想测试数组中 至少有一个元素 通过测试,那么可以使用 some。就像是 map,filter,和 find,some 用回调函数作为参数。它返回 ture,如果至少一个元素通过测试,返回 true 否则返回 false。
当你处理权限问题的时候,可以使用 some:
const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], }, ] const hasDeletePermission = users.some(user => user.permissions.includes('delete') ) console.log(hasDeletePermission) // true
every
类似 some,不同的是 ever 测试了所有的元素是否满足条件(而不是 至少一个)。
const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], }, ] const hasAllReadPermission = users.every(user => user.permissions.includes('read') ) console.log(hasAllReadPermission) // false
flat(ES2019)
这是一个即将到来的招牌方法, 在JavaScript 世界中。大致而言,flat 穿件一个新数组,通过组合所有的子数组元素。接受一个参数,数值类型,代表你想展开的深度。
const numbers = [1, 2, [3, 4, [5, [6, 7]], [[[[8]]]]]] const numbersflattenOnce = numbers.flat() console.log(numbersflattenOnce) // [1, 2, 3, 4, Array[2], Array[1]] const numbersflattenTwice = numbers.flat(2) console.log(numbersflattenTwice) // [1, 2, 3, 4, 5, Array[2], Array[1]] const numbersFlattenInfinity = numbers.flat(Infinity) console.log(numbersFlattenInfinity) // [1, 2, 3, 4, 5, 6, 7, 8]
flatMap(ES2019)
猜猜这个方法干什么?我打赌你可以做到顾名思义。
首先在每个元素上运行一个 mapping 方法。接着一次性展示数据。十分简单!
const sentences = [ 'This is a sentence', 'This is another sentence', "I can't find any original phrases", ] const allWords = sentences.flatMap(sentence => sentence.split(' ')) console.log(allWords) // ["This", "is", "a", "sentence", "This", "is", "another", "sentence", "I", "can't", "find", "any", "original", "phrases"]
这个例子中,数组里有一些句子,然而我们想得到所有的单词。不使用 map 去把所有的句子分割成单词然后展开数组,你可以直接使用 flatMap。
与 flatMap 无关的,你可以使用 reduce 方法来计算单词的数量(只是展示另一种 reduce 的用法)
const wordsCount = allWords.reduce((count, word) => { count[word] = count[word] ? count[word] + 1 : 1 return count }, {}) console.log(wordsCount) // { This: 2, is: 2, a: 1, sentence: 2, another: 1, I: 1, "can't": 1, find: 1, any: 1, original: 1, phrases: 1, }
flatMap 经常用于响应式编程,这里有个例子。
join
如果你需要基于数组元素创建字符串,join 正是你所寻找的。它允许通过链接数组元素来创建一个新的字符串,通过提供的分割符分割。
举个例子,你可以使用 join 一眼展示活动的参与者:
const participants = ['john', 'mary', 'gary'] const participantsFormatted = participants.join(', ') console.log(participantsFormatted) // john, mary, gary
下面的例子更真实,在于你想先过滤参与者然后得到他们的名字。