0 引子
JavaScript中数组 Array
的方法有: at、concat、copyWithin、entries、every、fill、filter、find、findIndex、flat、flatMap、forEach、from、includes、indexOf、isArray、join、keys、lastIndexOf、map、pop、push、reduce、reduceRight、reverse、shift、slice、some、sort、splice、toLocaleString、toString、unshift、values、valueOf
。 方法太多,“好记性不如烂笔头”,索性就做个总结了。
0.1 数组创建(Array.from)
在介绍方法前啰嗦几句数组的基础知识。
let arr = new Array() // [] 得到一个空数组
let arr = new Array(3) // [] 得到一个空数组,但数组的长度 arr.length 为 3
let arr = new Array(3).fill(1) // [1,1,1] 得到一个包含 3 个 1 的数组
let arr = [] // [] 和 new Array() 效果一样
let arr = [1,1,1] // [1,1,1] 和 new Array(3).fill(1) 效果一样
除了以上创建方法外,还有些特殊的:
const arr = [1,2,3]
在结果上和使用 let
创建数组是一致的,但用 const
定义的数组不允许修改地址,因此不能在创建数组之后再进行类似于 arr = [3,2,1]
这样的操作。
let arr = Array.from([1,2,3])
Array.from()
这个方法非常强大,由于它基本在创建数组时使用,就在这里简单介绍一下。
语法:Array.from(object, mapFunction, thisValue)
。
有3个参数:
object
必要参数,数组来源;mapFunction
可选参数,操作函数;thisValue
可选参数,外部this
引入。
举几个实用的例子:
let arr = Array.from([1,2,3]) // [1,2,3]
let arr = Array.from('abc') // ['a','b','c']
let arr = Array.from(new Set([1,2,3])) // [1,2,3]
let arr = Array.from(new Map([['a', 2], ['b', 2]])) // [['a', 2], ['b', 2]] 二维数组
简单的来说,
Array.from()
可以提取数组,来源可以是数组、字符串、Set对象、Map对象等一切看起来像数组的东西。
创建二维数组:
let arr = new Array(m).fill(0).map(() => new Array(n).fill(1)) // m 行 n 列,内容全是 1
推荐用这个方式创建二维数组(m
行n
列),其中 fill(0)
里的 0
可以换成任何值,反正最终都会被 new Array(n).fill(1)
替换。先记住创建方法,具体的 fill
map
方法后面再详细介绍。
闲话少叙,接下来就正式开始数组方法了!
将数组的方法大致分为三大类:索引类、操作类和判断类。
1 索引类
包含方法
at、entries、forEach、keys、reduce、reduceRight、values
。
数组的索引序列 0 1 2 3 ... n-1
( n
为数组长度)。
let arr1 = [1,2,3] // [1,2,3]
arr1[0] // => 1
arr1[2] // => 3
arr1[3] // => undefined 当索引大于等于数组长度,就会返回 undefined
1.1 at
语法:array<number>.at(index: number): number | undefined
。
功能:根据索引定位元素。
参数只有1个必要参数:数组的索引值。
arr1.at(0) // => 1 效果同 arr1[0]
可见效果与方括号类似,但需要特别注意:
arr1.at(-1) // => 3 效果同 arr1[2]
arr1.at(-4) // => undefined
这里的索引值可以是负值,负值可以理解为倒着数,-1
就是倒数第1个,-2
就是倒数第2个,这个负值不允许小于 -arr1.length
,也就是说索引值 index
的取值范围 [-arr1.length, arr1.length-1]
。
1.2 entries、keys、values
功能:提供遍历接口。
这3个方法放在一起看,entires
表示键值对数组,keys
表示索引数组,values
表示值数组,但这3个方法不能单独使用,需要和 for of
一起才有效。
for (let i of arr1.entries()) console.log(i) // 依次打印键值对 [0,1] [1,2] [2,3]
for (let key of arr1.keys()) console.log(key) // 依次打印索引 0 1 2
for (let value of arr1.values()) console.log(value) // 依次打印值 1 2 3
1.3 forEach
语法:array.forEach(function(currentValue, index, arr), thisValue)
功能:遍历数组。
回调函数的参数有3个:
currentValue
必要参数,为当前值;index
可选参数,为当前值索引;arr
可选参数,为数组本身。
此外,还有一个可选参数 thisValue
,用来引入外部 this
。
arr1.forEach((value, index, arr) => { console.log(value, index, arr) }) // 依次打印值 索引 数组本身
// 1 0 [1,2,3]
// 2 1 [1,2,3]
// 3 2 [1,2,3]
实现的效果和 for of
搭配 entries、keys、values
的效果类似,但需要注意, forEach
的循环是不可暂停的,即使执行 return
,也只能起到类似于 continue
的效果。
1.4 reduce、reduceRight
语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
。
功能:从左往右遍历数组,在遍历的过程中进行操作,并记录操作结果,遍历结束时输出结果。reduceRight
方法则是从右往左遍历数组,其他和 reduce
一致。
回调函数的参数有4个:
total
必要参数,为操作结果;currentValue
必要参数,为当前值;currentIndex
可选参数,为当前值;arr
可选参数,为数组本身。
此外,还有一个可选参数 initialValue
,作为操作结果 total
的初始值。
以数组求和作为例子:
let result = arr1.reduce((total, curVal) => total + curVal, 0)
console.log(result) // 6 即 0+1+2+3 = 6
result = arr1.reduce((total, curVal) => total + curVal, 10)
console.log(result) // 16 即 10+1+2+3 = 16
再来一个进阶例子:
let arr2 = [10, 20, 30, 40]
let result = arr2.reduce((output, curVal, curIndex) => {
if (curVal > 20) output.push([curVal, curIndex])
return output
}, [])
console.log(result) // [[30, 2], [40, 3]]
需要注意的点:
initialValue
虽然是可选参数,但建议将之作为必要参数使用,严格控制输出量的初始值;initialValue
的数据类型必须与必要参数total
保持一致。
2 操作类
包含方法
concat、copyWithin、fill、flat、flatMap、join、map、pop、push、reverse、shift、slice、sort、splice、toLocaleString、toString、unshift、valueOf
。
在讲操作方法之前,再多说两句:数组可以是不连续的。
let arr3 = [1,2,3]
arr3[5] = 4
console.log(arr3) // [1,2,3,undefined,undefined,4] 可以是不连续的
console.log(arr3.length) // 6 长度为 6
可以看到不连续是伪不连续,当不连续的索引 5
被赋值后,实际索引 3、4
虽然为 undefined
,但数组空间已经开辟。这种“不连续”的数组并不安全,实际对数组进行操作时尽量避免这种情况发生。
2.1 pop、push、shift、unshift
还记得《计算机原理》中的“堆栈”吗?数组实际上是“栈”,但又不完全是。“栈”的逻辑是严格的“先入后出”,而JS中的数组即遵循“栈”的逻辑,但又给“先入”的元素提供了“先出”的机会,也给“后来”的元素一个“插队”的机会(或者说,数组的也可以是“队列”)。
语法:array.pop()/.shift()
、array.push(item,item2,...)/.unshift(item,item2,...)
功能:
pop
移除数组末尾(右端)的值,即“出栈”,返回移除的值;push
从数组末尾(右端)添加值item,itme2,...
,即“入栈”,返回数组长度;shift
移除数组头部(左端)的值,返回移除的值;unshift
从数组头部(左端)添加值item,itme2,...
(顺序不变),返回数组长度。
四个方法都会改变原数组。
两个压栈的方法 push
、unshift
必须要有至少 1 个参数,如果有多个参数就按当前顺序一并入栈。
例子:
// 假设进行操作前所有的 arr1 == [1,2,3]
// pop
arr1.pop() // => 3 [1,2,3] 经过 pop 后变为 [1,2],输出 3
// push
arr1.push(4) // => 4 [1,2,3] 经过 push(4) 后变为 [1,2,3,4],输出数组长度 4
arr1.push(4,5) // => 5 [1,2,3] 经过 push(4,5) 后变为 [1,2,3,4,5],输出数组长度 5
// shift
arr1.shift() // => 1 [1,2,3] 经过 shift 后变为 [2,3],输出 1
// unshift
arr1.unshift(4,5) // => 5 [1,2,3] 经过 unshift(4,5) 后变为 [4,5,1,2,3],输出数组长度 5
需要注意的是:运行一次 shift
或 unshift
的时间远大于运行一次 pop
或 push
的时间,因此尽量使用pop
和 push
方法,特别是在做循环时,一旦在循环中使用 shift
或 unshift
方法,计算的耗时将大大降低系统的响应速度。
操作类方法数量比较多,为方便查询下面将按首字母顺序进行,关联较大的方法会放在一起讲。
2.2 concat
语法: array1.concat(array2, array3, ...)
。
功能:将若干个数组连接起来,保存到一个新数组并输出。(注意:所有的原数组都不会改变!)
至少有1个参数,所有参数按顺序入栈。经测试,参数的数据类型基本没有要求,可以是数值 number
、字符串 string
、 数组 number[] 、string[]
,也可以是undefined、null
或者自定义的类型,甚至是对象 Set、Map、Object
,但需要注意: 这些数据除了数组会被解包,其他都会原封不动的作为新数组的一个元素存在。
例子:
let arr4 = ['a']
arr4.concat(['b','c']) // => ['a','b','c'] 数组会被解包
arr4.concat(['b'],['c']) // => ['a','b','c']
arr4.concat(1,[2],'c',null) // => ['a',1,2,'c',null] 其他类型的数据也会依次连接
arr4.concat(new Set([1,2,3]), new Map([['a', 1]]) // => ['a', Set(3), Map(1)] 对象原封不动
arr4 // => ['a'] cancat 不会影响原数组,包括参数中的数组或其他类型数据
2.3 copyWithin
语法: array.copyWithin(target, start, end)
功能:从数组指定位置 target
开始,用 [start,end)
(含左不含右)间的元素将之覆盖,并输出覆盖完成后的数组。这个方法会改变原数组,但永远不会增减原数组的长度。
有3个参数:
target
必要参数,被覆盖的起始位置(含);start
可选参数,默认值0
,用于覆盖元素的起始位置(含);end
可选参数,默认值array.length
(不含),用于覆盖元素的结束位置(不含)。
例子:
let arr5 = [1,2,3,4,5] // 假设以下每个操作前 arr5 都为 [1,2,3,4,5]
arr5.copyWithin(2,0,2) // => [1,2,1,2,5] 从索引 2 开始,用[0,2)的元素即 1 2 进行覆盖
arr5.copyWithin(2,1) // => [1,2,2,3,4] 从索引 2 开始,用[1,)的元素即 2 3 4 5 进行覆盖,多了不会增加
arr5.copyWithin(2) // => [1,2,1,2,3] 从索引 2 开始,用[0,)的元素即 1 2 3 4 5 进行覆盖
2.4 fill
语法: array.fill(value, start, end)
功能:用数据 value
,将 [start,end)
(含左不含右)间的元素一一覆盖,并输出覆盖完成后的数组。这个方法会改变原数组。
有3个参数:
value
必要参数,用于覆盖的值;start
可选参数,默认值0
,被覆盖元素的起始位置(含);end
可选参数,默认值array.length
(不含),被覆盖元素的结束位置(不含)。
例子:
// 假设以下每个操作前 arr5 都为 [1,2,3,4,5]
arr5.fill(6,0,2) // => [6,6,3,4,5] 用值 6 对索引[0,2)的元素即 1 2 进行覆盖
arr5.fill(6,1) // => [1,6,6,6,6] 用值 6 对索引[1,)的元素即 2 3 4 5 进行覆盖
arr5.fill(6) // => [6,6,6,6,6] 用值 6 对所有元素进行覆盖
arr5.fill([7,8],1,3) // => [1,[7,8],[7,8],4,5]
arr5.fill(new Set([1,2,3]),0,2) // => [Set(3),Set(3),3,4,5]
任何数据类型的值理论上都可以用于覆盖,该值不会被解包。注意 fill
和 copyWithin
的区别,fill
中 [start,end)
表示被覆盖的位置,而 copyWithin
中 [start,end)
是用于覆盖的值的索引。
2.5 flat
语法: array.flat(depth)
。
功能:将数组展开 depth
层,并作为新数组输出。该方法不会改变原数组!
只有一个可选参数 depth
,默认值 1
。
例子:
let arr6 = [1,2,[3,[4,[5]]],[6]]
arr6.flat(1) // => [1,2,3,[4,[5]],6] 展开 1 层
arr6.flat(3) // => [1,2,3,4,5,6] 展开 3 层
arr6.flat(5) // => [1,2,3,4,5,6] 因为原数组最大只有 3 层,这里实际只展开了 3 层
arr6.flat(Inifity) // => [1,2,3,4,5,6] 无论有多少层都全部展开
arr6.flat() // => [1,2,3,[4,[5]],6] 默认展开 1 层,等于 arr6.flat(1)
2.6 flatMap
语法: array.flatMap(function(currentValue,index,arr), thisValue)
。
功能: 对数组先执行 map
后再执行 flat
。该方法不会改变原数组!
回调函数的3个参数:
currentValue
必要参数,表示当前值;index
可选参数,表示当前索引;arr
可选参数,表示数组本身。
此外,还有一个可选参数 thisValue
,用来引入外部 this
。
这个方法就是 map
和 flat
的合并,例子用法可以直接看 2.8小节map
和 2.5小节flat
。
2.7 join
语法: array.join(separator)
。
功能: 将数组用分隔符 separator
连接组成字符串并输出。该方法不会改变原数组!
只有一个可选参数,默认值 ,
。
例子:
// arr1 == [1,2,3]
arr1.join('-') // => 1-2-3 用 '-' 将元素 1 2 3 连接
arr1.join(5) // => 15253 用 5 将元素 1 2 3 连接
arr1.join() // => 1,2,3 默认用 ',' 将元素 1 2 3 连接
arr1.join('') // => 123 直接将元素 1 2 3 连接
arr1.join(' ') // => 1 2 3 用 ' ' (空格)将元素 1 2 3 连接
[new Set(arr), 1].join('-') // => [object Set]-1 任何形式的数组元素都可以连接
注意,任何数据类型的数组元素都可以被连接,但连接完的输出必然是 string
类型。
join
和 split
这两个方法可以组合记忆,这里扩展下 string
类型的 split
方法。
语法: string.split(separator,limit)
。
功能:在字符串中查找 separator
字符串,从找到的位置处分割字符串(separator
字符串不会被保留),分割完的字符串保存到新的数组中并输出。该方法不会改变原字符串!
有2个参数:
separator
可选参数,默认为空(指不分割),理论上可以是任何类型的数据;limit
可选参数,输出数组的长度限制,默认为不限制数组长度。
例子:
let str1 = '1*2*3'
str1.split('*') // => [1,2,3] 用 '*' 分割字符串
str1.split('1') // => ['','2*3'] 用 '1' 分割字符串,注意边缘位置的分割
'111'.split('1') // => ['','','',''] 用 '1' 分割字符串,可以分割出空字符(注意有多少个空字符)
str1.split('') // => ['1','*','2','*','3'] 用空字符分割,表示将所有都分隔开
str1.split() // => ['1*2*3'] 默认为空,指没有任何字符符合条件,因此整个字符串存入数组
str1.split('',3) // => ['1','*','2'] 用空字符分割,限制长度3,多出的长度会被截断
str1.split({'a': 1}) // => ['1*2*3'] 任何数据类型都会被转义成字符串用于分割(意义不大)
从用法可以理解 join
和 split
相当于相反的操作,放在一起有助于记忆。
2.8 map
语法: array.map(function(currentValue,index,arr), thisValue)
。
功能: 从左往右遍历数组,在回调函数中对数组元素进行操作,操作的结果会保存到新的数组并输出。该方法不会改变原字符串!
回调函数的3个参数:
currentValue
必要参数,表示当前值;index
可选参数,表示当前索引;arr
可选参数,表示数组本身。
此外,还有一个可选参数 thisValue
,用来引入外部 this
。
例子:
// arr1 == [1,2,3]
arr1.map((curVal, index, arr) => {
console.log(curVal, index, arr)
return curVal * 2
}) // => [2,4,6] 会依次打印: 1 0 [1,2,3]; 2 1 [1,2,3]; 3 2 [1,2,3]
arr1.map((curVal) => curVal + 1) // => [2,3,4] 给每个元素 +1
2.9 reverse
语法: array.reverse()
。
功能: 将数组顺序反转。原数组会改变!
无参数。
例子:
// arr1 == [1,2,3]
arr1.reverse() // => [3,2,1] 将 [1,2,3] 顺序反转
这个方法简单粗暴,功能不用多说,可以结合 join
和 split
实现反转字符串的功能:
// str1 == '1*2*3'
str1.split('').reverse().join('') // => '3*2*1' 先将字符串分割成数组,然后反转数组,最后将数组拼接成字符串
需要注意:原字符串不会改变,需要接住输出的反转字符串。
2.10 slice
(substring、substr
)
语法: array.slice(start, end)
。
功能: 从数组中截取索引为 [start, end)
(含左不含右)的值,保存到新数组中并输出。该方法不会改变原数组!
有2个参数:
start
可选参数,默认值0
,表示截取起始位置(含);end
可选参数,默认值array,length
,表示截取结束位置(不含)。
例子:
// arr1 == [1,2,3]
arr1.slice(1,2) // => [2] 从 索引 1 的位置(含)截取到索引 2 的位置(不含)
arr1.slice(1) // => [2,3] 从索引 1 的位置截取到数组结束
arr1.slice(,1) // => [1] 从默认索引 0 的位置截取到索引 1 的位置(不含),为了可读性,建议不要这样写
arr1.slice() // => [1,2,3] 无参数,默认会截取整个数组,注意,此时返回的是一个新的数组,不是原数组(地址不同)
arr1.slice(-1) // => [3] 参数可以是负数,-1 表示数组右数第 1 个元素
arr1.slice(0,-1) // => [1,2] 从 索引 1 的位置(含)截取到右数第 1 个元素的位置(不含)
arr1.slice(-2,-1) // => [2] 从右数第 2 个位置(含)截取到右数第 1 个位置(不含)
// 加一些奇怪的代码
arr1.slice(2,1) // => [] start 在 end 右边时,截取为空
arr1.slice(4) // => [] start 大于等于 array.length 时截取到的为空
arr1.sclie(-5) // => [1,2,3] 当 start 小于 -array.length 时等于 0
// 以上这几个虽然可以运行,但不建议这么写代码,知道这种可能导致 bug 的存在就行
说到了数组的截取,顺便也提一下字符串的2个截取方法吧!
substring、substr
第1个 substring
语法: string.substring(from, to)
。
功能: 从字符串中截取索引为 [from, to)
(含左不含右)的字符串并输出。不会改变原字符串!
有2个参数:
from
必要参数,表示截取起始位置(含);to
可选参数,默认值string,length
,表示截取结束位置(不含)。
例子:
// str1 == '1*2*3'
str1.substring(2,3) // => '2' 从索引 1 的位置(含)截取到索引 2 的位置(不含)
str1.substring(3) // '*3' 从索引 3 的位置(含)截取到字符串末尾
str1.substring() // 报错,没有传递必要参数 from
str1.substring(-1) // '1*2*3' 小于 0 的 from 视为 0
str1.substring(6) // '' from 超过字符串长度,截取到空字符串
substring
和 slice
方法的使用极其相似,但需要注意:
substring
必须传参,最好养成好习惯,在slice
中也至少写上起始位置;substring
的负值参数与slice
含义不同,一定不要记混了。
第2个 substr
语法: string.substr(start, length)
。
功能: 从字符串的 start
位置开始截取 length
长度的字符串并输出。不会改变原字符串!
有2个参数:
start
必要参数,表示截取起始位置(含);length
可选参数,表示截取字符串的长度,默认会截取到字符串结束,如果剩余长度不够也会只截取到字符串结束。
例子:
// str1 == '1*2*3'
str1.substr(0,3) // => '1*2' 从索引 0 的位置(含)开始截取长度为 3 的字符串
str1.substr(1) // => '*2*3' 从索引 1 的位置(含)开始截取到字符串结束
str1.substr() // => '1*2*3' 截取整个字符串,等同于 str1.substr(0)
str1.substr(-1) // => '3' 惊不惊喜,这个负值又可以了!从右数第 1 个数开始截取到结束
str1.substr(-10, 3) // => '1*2' 当 start 小于 -string.length 时视为 0
substring
和 substr
同属字符串的截取方法,有共通之处,也有不同的地方,各位自行决定记哪个方法吧!不过需要注意,由于一些奇怪的原因,substr
可能随时会被 JS 弃用。
2.11 sort
语法: array.sort(function(a, b))
。
功能:将数组重新排序,并返回数组。原数组将被改变!
整个回调函数都是可选参数,具体回调函数的写法下面说明。
例子:
let arr7 = [3,4,5,40,1,21] // 假设以下每次操作前的 arr7 都是初始值
arr7.sort() // => [1,21,3,4,40,5]
乍一看这个默认的排序方式让人摸不着头脑,起始就是默认的排序方法会将所有元素作为字符串进行比对,在 JS 中字符串的比大小就是从左往右逐位进行比较。
如果想要实现数值大小排序,可以这么写:
arr7.sort((a, b) => a - b) // => [1, 3, 4, 5, 21, 40] 非降序排列
arr7.sort((a, b) => b - a) // => [40, 21, 5, 4, 3, 1] 非升序排列
以上算法可以理解为 a、b
两个参数就是冒泡法中对比的两个值,=> a - b
意味着当 a > b
时返回值为 true
,此时要交换位置;a <= b
时返回值为 false
,此时不用交换位置,这样就实现了非降序排列。 => b - a
与之相反,实现了非升序排列。
sort
有很多巧妙的使用方法,举一例即可见一斑:
let arr8 = [['x',2],['y',1],['z',3]]
arr8.sort((a, b) => b[1] - a[1]) // => [['z',3],['x',2],['y',1]]
可以想象以上代码的场景可以是:有一张表,表中的数据表示产品 x
销售量 2
;产品 y
销售量 1
;产品 z
销售量 3
,排序过程中取到的 a、b
都是数组,只要将其中对应销售量的位(索引 1)进行对比,即可得到根据销售量的排序结果。这里的数组 ['x',2]
如果换成对象 {name: 'x', number: 2}
也可以进行类似的操作 => b.number - a.number
。
2.12 splice
语法: array.splice(index, howmany, item1, item2, ...)
。
功能: 从数组中索引为 index
的位置(含)开始,删除 howmany
个元素,然后将 item1, item2, ...
插入到删除的位置,输出删除元素组成的新数组。原数组会因此改变!
有2个参数:
index
必要参数,表示删除的起始位置(含);howmany
可选参数,表示要删除的元素数量,默认值从起始位置(含)一直删除到数组末尾;item1, item2, ...
可选参数,默认为空,表示要插入的值。
例子:
// arr1 == [1,2,3] // 假设以下操作之前 arr1 都是初始值
arr1.splice(1,2,4,5) // => [2,3] 从索引 1 的位置开始,删除 2 个元素(2 3),然后将 4 5 插入
// 结束后,arr1 变为 [1,4,5]
arr1.splice(1,0,4) // => [] 从索引 1 的位置开始,删除 0 个元素(即没有删除任何值),然后将 4 插入
// 结束后,arr1 变为 [1,4,2,3],注意插入的位置
arr1.splice(1) // => [2,3] 默认从索引 1 的起始位置(含)一直删除到数组末尾
// 结束后,arr1 变为 [1]
splice
是会改变原数组的,一般使用场景就是删除、插入,要注意输出值是删除掉的元素组成的新数组。经测试,这个方法的时间成本不小,不建议在循环中使用。
2.13 toLocaleString、toString、valueOf
语法: array.toLocaleString()/.toString()/.valueOf()
。
三个方法的语法完全一样,而且无参,功能如下:
toLocaleString
将数组元素转化为本地字符串,用,
连接形成字符串并输出;toString
将数组元素转化为本地字符串,用,
连接形成字符串并输出;valueOf
输出数组的原始值。
这三个方法都不会改变原数组。
例子:
// arr1 == [1,2,3]
arr1.toLocaleString() // => 1,2,3
[1,2,new Date()].toLocaleString() // => 1,2,2023/3/15 15:47:33
arr1.toString() // => 1,2,3
[1,2,new Date()].toString() // => 1,2,Wed Mar 15 2023 15:47:33 GMT+0800 (中国标准时间)
arr1.valueOf() // => [1,2,3]
arr1.valueOf() === arr1 // => true
直接给结论:
- 对于数组来说,
toLocaleString、toString
这两个方法功能基本一致,只有在转化时间类型(Date对象)的数据时,结果字符串内容形式会有不同; valueOf
这个方法输出结果与原数组恒等(===
)。
3 判断类
包含方法
every、filter、find、findIndex、includes、indexOf、isArray、lastIndexOf、some
。
3.1 isArray
语法: Array.isArray(object)
。
功能:判断目标值是否为数组。注意这个方法的使用,原数据要放在括号里!原数据不会改变。
只有一个必要参数 object
,可以是任何数据类型。
例子:
Array.isArray([1,2]) // => true [1,2] 是数组
Array.isArray([3,'c']) // => true [3,'c'] 是数组
Array.isArray(1) // => false 1 不是数组
Array.isArray('abc') // => false 'abc' 不是数组
Array.isArray(new Set([1,2,3])) // => false Set(3) 不是数组
3.2 indexOf、lastIndexOf
语法: array.indexOf(item, start)
。
功能:在数组中从左往右,查找第一个 item
的索引值,没有则返回 -1
。 lastIndexOf
是从右往左查,即查到的是倒数第一个 item
的索引值,没有则返回 -1
。
有2个参数:
item
必要参数,表示搜索的值;start
可选参数,开始搜索的位置,默认值0
(lastIndexOf
中默认值为array.length-1
),取值范围[0, array.length-1]
。
例子:
// indexOf
arr1.indexOf(2) // => 1 [1,2,3] 中第一个 2 的索引为 1
arr1.indexOf(2,2) // => -1 从索引 2 的位置(含)开始往后查找,没有值为 2 的元素
// lastIndexOf
arr1.lastIndexOf(2,0) // => -1 从索引 0 的位置(含)开始往前查找,没有值为 2 的元素
3.3 includes
语法: array.includes(item, fromIndex): boolean
。
功能:在数组中从左往右,查找是否包含 item
,有则返回 true
,没有返回 false
。
有2个参数:
item
必要参数,表示搜索的值;fromIndex
可选参数,开始位置,默认值0
,取值范围[-array.length, array.length-1]
(取值范围和at
方法一样,可以是负值,和indexOf、lastIndexOf
里对应参数的要求是不一样的)。
例子:
arr1.includes(2) // => true [1,2,3] 中有 2
arr1.includes(2,1) // => true 从索引 1 的位置(含)开始往后查找,有 2
arr1.includes(2,2) // => false 从索引 2 的位置(含)开始往后查找,没有 2
3.4 every、filter、find、findIndex、some
语法: array.every(function(currentValue,index,arr), thisValue)
。
这一小节中5个方法的是使用都是一样的,功能略有不同:
every
遍历所有元素,判断是否所有元素均满足条件,均满足返回true
,否则返回false
;some
从左往右遍历元素,找到第一个满足条件的值后返回true
,全不满足返回false
;filter
从左往右遍历所有元素,将满足条件的元素保存至新建的空数组中,遍历结束输出数组;find
从左往右遍历元素,将第一个满足条件的值输出,全不满足则返回undefined
;findIndex
从左往右遍历元素,将第一个值满足条件的索引输出,全不满足则返回-1
。
5个方法的参数均一样,回调函数有3个的参数:
currentValue
必要参数,表示当前值;index
可选参数,表示当前索引;arr
可选参数,表示数组本身。
此外,还有一个可选参数 thisValue
,用来引入外部 this
。
例子:
// every
arr1.every((curVal) => curVal > 1) // => false [1,2,3] 中 1 不满足 > 1
arr1.every((curVal, index, arr) => {
console.log(curVal, index, arr)
return curVal > 1
}) // => false 会依次打印: 1 0 [1,2,3]; 2 1 [1,2,3]; 3 2 [1,2,3]
// some
arr1.some((curVal) => curVal > 1) // => true 遍历到 2 的时候终止,并输出 true
arr1.some((curVal, index, arr) => {
console.log(curVal, index, arr)
return curVal > 1
}) // => true 当找到满足条件时停止,打印结果: 1 0 [1,2,3]; 2 1 [1,2,3]
// filter
arr1.filter((curVal) => curVal > 1) // => [2,3] 满足 > 1 的值放入新数组并输出
arr1.filter((curVal) => curVal > 3) // => [] 没有 > 3 的值
// find
arr1.find((curVal) => curVal > 1) // => 2 第一个满足 > 1 的值为 2
arr1.find((curVal) => curVal > 3) // => undefined 没有 > 3 的值
// findIndex
arr1.findIndex((curVal) => curVal > 1) // => 1 第一个满足 > 1 的值的索引为 1
arr1.findIndex((curVal) => curVal > 3) // => -1 没有 > 3 的值
注意:所有回调函数都必须是判断条件。
结语
数组的方法很多,但并非每个都会频繁使用,因此 主要记功能!主要记功能!主要记功能! 只要记住有这个功能,如果忘记了使用方式,可以随时根据方法名上网查找,也欢迎大家常来这里看看。
到此,数组所有方法都总结完毕,希望能够帮助到看文章的你!
笔记主要为自用,欢迎友好交流!