JavaScript数组方法

前言:在 JavaScript 中,数组是很重要的数据类型,在日常工作中也必不可少,但是对于数组的各种方法 API 却了解不多,或者是只知其名,不知其何用。本文主要是归纳总结各种数组方法,包括 ES5 和 ES6 中新增的

数组

数组对象是一个有序的数据(数据可以是 原始类型 或 对象类型)集合。相对于变量,数组可用于在一个变量中存储多个变量值。数组中的每一项都有一个数字附于其上,被称为索引,索引从0开始计数。

数组允许最后一个元素仍然带有逗号

1
[1, 2, 3,]

创建数组

  • 采用 Array 对象进行创建
1
2
3
var arr1 = new Array() // 创建空数组
var arr2 = new Array(10) // 创建长度为10的数组,初始值都为 undefined
var arr3 = new Array('a', 'b', 'c') // 创建包含3个字符串的数组
  • 数组字面量
1
var arr = [1, 2, 3]

数组修改器方法(变异方法)

修改器方法(变异方法),指的是会改变被这些方法调用的原始数组

copyWith()

浅复制数组的一部分到同一数组中的另一个位置,并返回它

arr.copyWithin(target[, start[, end]])

接收三个参数,target 是复制到该位置,会替换原来的元素;start 是开始复制的位置;end 是结束复制的位置

1
2
['a', 'b', 'c', 'd'].copyWith(1, 2, 3) // 从索引2开始复制到索引3,也就是复制元素‘c’,到目标位置——索引1
// 输出 ['a', 'c', 'c', 'd']

fill()

用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。

arr.fill(value[, start[, end]])

接收三个参数,value 是用来填充的值;start 是开始填充的索引,默认为0;end 是结束填充的索引,默认是数组长度

1
2
[1, 2, 3, 4].fill(0, 2, 3)
// 输出[1, 2, 0, 4]

pop()

常用的数组方法,从数组中删除最后一个元素,并返回这个元素,改变数组长度

1
2
[1, 2, 3, 4].pop()
// 输出4,数组变为 [1, 2, 3]

push()

常用的数组方法,在数组的末尾增加一个或多个元素,并返回数组的新长度

1
2
[1, 2, 3, 4].push(5, 6)
// 输出数组长度6

基于数组的 push 和 pop 方法,可实现栈的入栈和出栈操作

reverse()

将数组反转,并返回该数组的引用。

1
2
[1, 2, 3].reverse()
// [3, 2, 1]

shift()

删除数组的第一个元素,并返回这个元素

1
2
[1, 2, 3].shift()
// 输出 1,数组变为 [2, 3]

基于数组的 push 和 shift 方法,可实现队列的入队和出队操作

unshift()

常用的数组方法,在数组的开头增加一个或多个元素,并返回数组的新长度

1
2
[1, 2, 3, 4].push(5, 6)
// 输出数组长度6

sort()

对数组元素进行排序,并返回当前数组,默认排序顺序是根据字符串Unicode码顺序;可传入用来指定按某种顺序进行排列的函数。

1
2
3
4
5
6
7
['c', 'b', 'a'].sort()
// 输出 ['a', 'b', 'c']
[3, 2, 5, 4, 1].sort((a, b) => {
return a - b
})
// 输出 [1, 2, 3, 4, 5]

splice

应重点关注的数组方法,可对数组进行删除/增加元素。

返回由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。

arr.splice(start[, deleteCount[, item1[, item2[, …]]]])

start 是开始修改的位置索引,deleteCount 是删除数组元素的个数,后续参数是指新插入的数组元素

1
2
[1, 2, 3, 4, 5].splice(2, 2, 0, 0)
// 输出被删除元素组成的数组[3, 4],原数组变为 [1, 2, 0, 0, 5]

数组访问方法(非变异方法)

数组访问方法(非变异方法),不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值

concat()

将当前数组与多个数组或非数组值连接,返回一个新数组

1
2
[1, 2, 3].concat(4, 5)
// 输出新数组 [1, 2, 3, 4, 5],原数组不变

includes()

判断当前数组是否包含某指定的值,如果是返回 true,否则返回 false

arr.includes(searchElement, fromIndex)

接收两个参数,查找的值,开始查找的索引

1
2
[1, 2, 3].includes(2)
// 输出 true

join()

将数组转换成字符串,可传入参数来分隔数组的每个元素,默认为逗号

1
2
['a', 'b', 'c'].join('+')
// 'a+b+c'

slice()

截取当前数组中的一段元素组合成一个新数组,并返回这个新数组

arr.slice(begin, end)

最多可接收两个参数,开始截取的位置索引和结束截取的位置索引

1
2
['a', 'b', 'c'].slice(1)
// 输出 ['b', 'c']

注意 slice() 和 splice() 的区别,slice 不改变原数组,splice 会改变原数组

toString()

返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。

1
2
['a', 'b', 'c'].toString()
// 'a,b,c'

toLocaleString()

返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 Object.prototype.toLocaleString() 方法。

indexOf()

返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1

接收两个参数,查找的值,开始查找的索引

1
2
[1, 2, 3, 2, 5].indexof(2)
// 输出索引1

lastIndexOf()

返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1

接收两个参数,查找的值,开始查找的索引

1
2
[1, 2, 3, 2, 5]. lastIndexOf(2)
// 输出索引3

迭代(遍历)方法

forEach()

对数组中的每个元素执行一次提供的函数

forEach 中设置的函数,可传入三个值:currentValue(数组当前项), index(数组当前项索引), array(操作的数组)

1
2
3
4
['a', 'b', 'c', 'd'].forEach((item, index, array) => {
console.log(`${item}的索引是${index}`)
console.log(array[index] === item)
})

every()

测试数组的所有元素是否都通过了指定函数的测试,返回 true 或 false

1
2
3
4
[1, 2, 3, 4].every((item) => {
return item > 2
})
// 输出 false

some()

测试数组中的某些元素是否通过由提供的函数实现的测试

1
2
3
4
[1, 2, 3, 4].some((item) => {
return item > 2
})
// 输出 true

filter()

将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回

1
2
3
4
[1, 2, 3, 4].filter((item) => {
return item > 2
})
// 输出新数组 [3, 4]

map()

创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果

1
2
3
4
[1, 2, 3].map(item => {
return item * 2
})
// 返回新数组 [2, 4, 6],原数组不变

其他技巧

1
2
3
4
var str = '12345'
Array.prototype.map.call(str, function(x) {
return x
}).reverse().join('')

reduce()

从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值

reduce 方法可传入两个参数,callback 和 初始值(initialValue)。

callback 函数可传入四个参数:accumulator(上一次调用回调时返回的累积值),currentValue(数组正在处理的值),currentIndex(数组当前处理的元素的索引),array(被处理的数组)

1
2
3
4
5
6
[1, 2, 3, 4].reduce((accumulator, currentValue) => {
return accumulator + currentValue
}, 5)
// 5 + 1 + 2 + 3 + 4
// 输出 15

其他技巧

reduce 是十分灵活并且十分实用的数组方法,应该完全掌握它!

  • 计算数组中每个元素出现的次数
1
2
3
4
5
6
7
8
9
10
['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'].reduce((allNames, name) => {
if (name in allNames) {
allNames[name]++
} else {
allNames[name] = 1
}
return allNames
}, {})
// 输出 { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
  • 数组去重
1
2
3
4
5
6
7
[1,2,1,2,3,5,4,5,3,4,4,4,4].sort().reduce((init, current) => {
let length = init.length
if (length == 0 || init[length - 1] !== current) {
init.push(current)
}
return init
}, [])
  • 数字添加千分位分隔符
1
2
3
4
5
6
7
let num = 123456789
let str = num + '' // 转为字符串
str.split('').reverse().reduce((previousValue, currentValue, currentIndex) => {
return (currentIndex % 3 ? currentValue : currentValue + ',' ) + previousValue
})
// 输出 123,456,789

reduceRight()

从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值

reduceRight 跟 reduce 方法类似,只是遍历顺序是从右到左,而 reduce 是从左到右

1
2
3
4
5
6
var a = ['1', '2', '3', '4', '5']
var left = a.reduce((prev, cur) => { return prev + cur})
var right = a.reduceRight((prev, cur) => { return prev + cur})
console.log(left) // "12345"
console.log(right) // "54321"

find()

返回数组中满足提供的测试函数的第一个元素的值,如果都不符合,那么返回 undefined

1
2
3
4
[1, 2, 3, 4].find((item) => {
return item > 2
})
// 输出新数组 3

findIndex()

返回数组中满足提供的测试函数的第一个元素的索引,如果都不符合,那么返回 -1

1
2
3
4
[1, 2, 3, 4].findIndex((item) => {
return item > 2
})
// 输出索引 2

keys()

返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。

1
2
3
4
5
6
let arr = ["a", "b", "c"]
let iterator = arr.keys()
console.log(iterator.next()) // 输出 Object {value: 0, done: false}
console.log(iterator.next()) // 输出 Object {value: 1, done: false}
console.log(iterator.next()) // 输出 Object {value: 2, done: false}

values()

返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。

这是个实验性功能,主流浏览器尚未支持,Chrome 及Firefox可以用”arrSymbol.iterator“方法来代替values()方法

1
2
3
4
5
6
let arr = ["a", "b", "c"]
let iterator = arr.values()
console.log(iterator.next()) // 输出 Object {value: 0, done: false}
console.log(iterator.next()) // 输出 Object {value: 1, done: false}
console.log(iterator.next()) // 输出 Object {value: 2, done: false}

entries()

返回一个数组迭代器(Array Iterator)对象,该迭代器会包含所有数组元素的键值对

1
2
3
4
5
6
let arr = ["a", "b", "c"]
let iterator = arr.entries()
console.log(iterator.next().value) // 输出[0, "a"]
console.log(iterator.next().value) // 输出[0, "b"]
console.log(iterator.next().value) // 输出[0, "c"]

其他方法

Array.from()

从类数组对象或者可迭代对象中创建一个新的数组实例

1
Array.from('abc') // 输出 ['a', 'b', 'c']

经典案例,数组去重

1
2
let arr = [1, 2, 2, 3, 2, 4]
Array.from(new Set([...arr]))

Array.isArray()

用来判断某个变量是否是一个数组对象

1
2
3
4
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false

Array.of()

根据一组参数来创建新的数组实例,支持任意的参数数量和类型

1
2
3
4
5
Array.of(7) // [7]
Array.of(1, 2, 3) // [1, 2, 3]
Array(7) // 长度为7,元素都为 undefined的数组 [ , , , , , , ]
Array(1, 2, 3) // [1, 2, 3]

参考文档:Array In MDN

坚持原创技术分享,您的支持将鼓励我继续创作!