Javascript中数组的api详解

161 阅读14分钟

写这篇文章之后觉得掘金的排版真的是一言难尽,然后就看到别人的排版使用了 mdnice ,十分漂亮,所以也用了一下,教程是你的掘金文章本可以这么炫(博客美化工具一波带走),体验地址 markdown-nice体验地址, 官网是 mdnice 本来想把这篇文章直接用 mdnice 排版的,但是篇幅太长了,所以只能拆分一下。没法一下接收太多的同学可以点一下下面的链接。

前端开发过程中,数组是我们经常需要用到的,很多小伙伴包括我也是,对数组的方法就知道那么几个,总觉得够用就行,那不够用的时候咋办呢?百度呗。有时候觉得自己是真的在用代码改变世界吗?还是说就是在混日子,真就是在 “搬砖”?今天复盘一下数组的方法,这可能是比较全面的了。

1. 数组的增删改查

push()

       push方法主要是向数组的尾部添加一个或者多个元素,然后返回新数组的长度

let arr = []
let arrLen = arr.push(1,2,3,4)

console.log("返回数组的长度:", arrLen, ",新数组: ", arr)
// 返回数组的长度: 4 ,新数组:  [ 1, 2, 3, 4 ]

pop()

pop方法主要是删除数组的最后一个元素,并返回删除的元素

let arr = [1,2,3,5]
let deleteItem = arr.pop()

console.log("返回删除的元素: ", deleteItem, ",新数组:", arr) 
// 返回删除的元素: 5 ,新数组: [ 1, 2, 3 ]

unshift()

      unshift方法可向数组的头部添加一个或多个元素,并返回新数组的长度

let arr = []
let arrLen = arr.unshift(1,2,3,4)

console.log("返回数组的长度:", arrLen, ",新数组: ", arr)
// 返回数组的长度: 4 ,新数组:  [ 1, 2, 3, 4 ]

shift()

      shift 方法主要是删除数组的第一个元素,并返回删除的元素

let arr = [1,2,3,4]
let deleteItem = arr.shift()

console.log("返回删除的元素:", deleteItem, ",新数组:", arr)
// 返回删除的元素: 1 ,新数组: [ 2, 3, 4 ]

splice()

      splice方法可以传入多个参数,第一个参数代表数组添加/删除项目的起始下标,第二个参数代表要删除的元素的数量,第 n+2 个参数代表即将向数组添加的元素。以下将使用splice方法对数组实现增删改。splice方法的返回值是一个数组,数组里存放的是删除的元素

      使用splice删除数组元素

let arr = [1,2,3,4]
let deleteArr = arr.splice(1, 2)

// 以下标为 1/n 的元素开始,删除两个元素console.log("删除元素后的数组:", arr,"删除的元素:", deleteArr) 
// 删除元素后的数组: [ 1, 4 ] 删除的元素: [ 2, 3 ]

      使用splice修改数组元素

let arr = ["张三", "李四", "王五", "赵六"]
let deleteArr = arr.splice(1, 1, "熊大")
//  以下标为 1/n 的元素开始,删除一个元素,添加另外一个元素
console.log("修改后的数组:", arr,"删除的元素:", deleteArr)
// 修改后的数组: [ '张三', '熊大', '王五', '赵六' ] 删除的元素: [ '李四' ]

     使用splice添加数组元素

let arr = ["张三", "李四", "王五", "赵六"]
let deleteArr = arr.splice(1, 0, "熊大") 
//  以下标为 1/n 的元素开始,删除 0/n 个元素,在下标为 1/n 的位置添加 1/n 个元素

console.log("修改后的数组:", arr,"删除的元素:", deleteArr)
// 修改后的数组: [ '张三', '熊大', '李四', '王五', '赵六' ] 删除的元素: []

indexOf()

       indexOf 方法用于查找数组元素,可以返回某个指定的字符串值在字符串中首次出现的位置。如果数组中有指定的元素值,那么返回元素的下标,如果没有则返回 -1 。该方法有两个参数,第一个参数是要查找的元素,第二个参数是是要查找的起始下标。

let arr = ["张三", "李四", "王五", "赵六", "张三"]

let index1 = arr.indexOf("张三") 
let index2 = arr.indexOf('张三', 1) // 以下标为1开始查找元素
let notFind = arr.indexOf('熊二')

console.log("查找的数组:", arr)
console.log("有范围地查找元素:", index1, "无范围地查找元素的:", index2, "未查找到的返回值:", notFind)
// 查找的数组: [ '张三', '李四', '王五', '赵六', '张三' ]
// 有范围地查找元素: 0 无范围地查找元素的: 4 未查找到的返回值: -1

lastIndexOf()

       lastIndexOf也是用于查找数组元素,但是,它是从后面往前找,如果数组中有指定的元素值,那么返回元素的下标,如果没有则返回 -1 。该方法有两个参数,第一个参数是要查找的元素,第二个参数是是要查找的起始下标。

let arr = ["张三", "李四", "王五", "赵六", "张三"]

let index1 = arr.lastIndexOf("张三") 
let index2 = arr.lastIndexOf('张三', 1) // 以下标为1开始查找元素
let notFind = arr.lastIndexOf('熊二') 

console.log("查找的数组:", arr)
console.log("有范围地查找元素:", index1, "无范围地查找元素的:", index2, "未查找到的返回值:", notFind)

// 查找的数组: [ '张三', '李四', '王五', '赵六', '张三' ]
// 有范围地查找元素: 4 无范围地查找元素的: 0 未查找到的返回值: -1

findIndex()

       findIndex是用于查找元素的,它的返回值是返回第一个符合条件的元素的下标,如果没有查找到符合的元素,那么返回 -1。它可以传入两个参数,第一个参数是一个回调函数,数组中的每个元素都调用一次回调函数。在回调函数中可以写你要查找元素的条件,当条件成立为true时,返回该元素的下标,没有则返回 -1。第二个参数我们通常不会用到,但是也说一下,它可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。

let arr = [1,2,3,4]
let obj = {  name: '张三'}

// 第一个参数是一个回调函数,函数的形参有三个  数组元素:val,数组下标:index,原数组:array
// 如果要使用第二个参数,这里的函数不要使用箭头函数,箭头函数的作用大家可以去查,这里就不累述了// 
let index = arr.findIndex(function(val, index, array) {
  console.log('数组元素:', val, ",元素下标:", index, ', 原数组:', array, ",传入的对象:", this)
  return val <= 2
}, obj) // 传入一个对象,那函数内部的this 指向就改变了,即函数内部的环境上下文就改变了console.log('查找到符合条件的元素的下标:', index)

// 数组元素: 1 ,元素下标: 0 , 原数组: [ 1, 2, 3, 4 ] ,传入的对象: { name: '张三' }
// 查找到符合条件的元素的下标: 0

find()

      find可以用于查找元素,它的返回值是返回第一个符合条件的元素,如果没有,则返回undefined。它可以传入两个参数,这两个参数的跟findIndex是一样的,这里就不累述了。

let arr = [1,2,3,4]
let obj = {  name: '张三'}

// 第一个参数是一个回调函数,函数的形参有三个  数组元素:val,数组下标:index,原数组:array
// 如果要使用第二个参数,这里的函数不要使用箭头函数,箭头函数的作用大家可以去查,这里就不累述了
let index = arr.find(function(val, index, array) {   
    console.log('数组元素:', val, ",元素下标:", index, ', 原数组:', array, ",传入的对象:", this)  
    return val <= 2
}, obj) // 传入一个对象,那函数内部的this 指向就改变了,即函数内部的环境上下文就改变了

console.log('查找到符合条件的元素:', index)

// 数组元素: 1 ,元素下标: 0 , 原数组: [ 1, 2, 3, 4 ] ,传入的对象: { name: '张三' }
// 查找到符合条件的元素的下标: 0

includes()

      includes用于判断数组是否存在指定的值,它的返回值是一个布尔值,存在就返回true,不存在就返回false。它可以传入两个参数,第一个参数是要查找的元素,第二个参数是要查找的起始位置。

let arr = [1,2,3,4]let isExit = arr.includes(1, 0)

console.log("是否存在指定的元素:", isExit)
// 是否存在指定的元素: true

总结:想记住数组这么多的api是不太现实的,但是一般常用的还是需要记住的,记住诀窍就是增删改查。

数组循环

       数组循环有多种方式,在这里我就不比对那种循环之间的性能比较,纯属就说说它们的用法。

forEach()

       forEach方法第一个参数传入一个回调函数,回调函数有三个形参,分别是数组元素,元素下表,元素数组,第二个参数可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。返回值是 undefined。

let arr = [1, 2, 3, 4]let obj = {  name: "张三"}

let res = arr.forEach(function(val, index, arr) {
   console.log("数组元素:", val, "元素下标:", index, "原数组:", arr, '改变this指向:', this)
 }, obj)

console.log("返回值: ", res)

// 数组元素: 1 元素下标: 0 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 2 元素下标: 1 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 3 元素下标: 2 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 4 元素下标: 3 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 返回值:  undefined

map()

      map方法传入一个回调函数,回调函数有三个形参,分别是数组元素,元素下表,元素数组,第二个参数可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。返回值是一个新的数组。

let arr = [1, 2, 3, 4]let obj = {  name: "张三"}

let res = arr.map(function(val, index, arr) {
  console.log("数组元素:", val, "元素下标:", index, "原数组:", arr, "改变this指向:", this)
  return val + 1
}, obj)

console.log("返回一个新的数组: ", res, "原数组:", arr)

// 数组元素: 1 元素下标: 0 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 2 元素下标: 1 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 3 元素下标: 2 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 数组元素: 4 元素下标: 3 原数组: [ 1, 2, 3, 4 ] 改变this指向: { name: '张三' }
// 返回一个新的数组:  [ 2, 3, 4, 5 ] 原数组: [ 1, 2, 3, 4 ]

filter()

      filter方法传入一个回调函数,回调函数有三个形参,分别是数组元素,元素下表,元素数组,第二个参数可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。这个方法可以用于进行过滤筛选。它的返回值是一个过滤后的数组。

let arr = [1, 2, 3, 4]let obj = {  name: "张三"}

let res = arr.filter(function(val, index, arr) {
  console.log("数组元素:", val, "元素下标:", index, "原数组:", arr, "改变this的指向:", this)
  return val < 2
}, obj)

console.log("返回一个过滤后的数组: ", res, "原数组:", arr)
// 数组元素: 1 元素下标: 0 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 数组元素: 2 元素下标: 1 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 数组元素: 3 元素下标: 2 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 数组元素: 4 元素下标: 3 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 返回一个过滤后的数组:  [ 1 ] 原数组: [ 1, 2, 3, 4 ]

every()

      every方法传入一个回调函数,回调函数有三个形参,分别是数组元素,元素下表,元素数组,第二个参数可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。它的返回值是一个布尔值,如果数组元素都符合回调函数的条件,则返回 true,否则返回false。

let arr = [1, 2, 3, 4]let obj = {  name: "张三"}

let res = arr.every(function(val, index, arr) {
  console.log("数组元素:", val, "元素下标:", index, "原数组:", arr, "改变this的指向:", this)
  return val < 2
}, obj)

console.log("是否数组内部的所有成员都满足回调函数里到条件: ", res, "原数组:", arr)
// 数组元素: 1 元素下标: 0 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 数组元素: 2 元素下标: 1 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 是否数组内部的所有成员都满足回调函数里到条件:  false 原数组: [ 1, 2, 3, 4 ]

some()

     every方法传入一个回调函数,回调函数有三个形参,分别是数组元素,元素下表,元素数组,第二个参数可以传入一个任意类型的值,这个值可以改变第一个参数内部的this指向。它的返回值是一个布尔值,如果数组存在元素符合回调函数的条件,则返回 true,否则返回false。

let arr = [1, 2, 3, 4]
let obj = {  name: "张三"}

let res = arr.some(function(val, index, arr) {
  console.log("数组元素:", val, "元素下标:", index, "原数组:", arr, "改变this的指向:", this)
 return val < 2
}, obj)

console.log("是否数组内部的存在成员满足回调函数里到条件: ", res, "原数组:", arr)
// 数组元素: 1 元素下标: 0 原数组: [ 1, 2, 3, 4 ] 改变this的指向: { name: '张三' }
// 是否数组内部的存在成员满足回调函数里到条件:  true 原数组: [ 1, 2, 3, 4 ]

entries()

      entries方法不传入任何参数,它返回一个数组的迭代对象,该对象包含数组的键值对 (key/value)。可以用for...of... 进行循环

let arr = [1, 2, 3, 4]

for(let [key, value] of arr.entries()) {
  console.log("数组下标:", key,"数组元素:", value)
}

// 数组下标: 0 数组元素: 1
// 数组下标: 1 数组元素: 2
// 数组下标: 2 数组元素: 3
// 数组下标: 3 数组元素: 4

keys()

      keys方法不传入任何参数,它返回一个数组的迭代对象,该对象包含数组的键(key)。可以用for...of... 进行循环

let arr = [1, 2, 3, 4]

for(let key of arr.keys()) {
  console.log("数组下标:", key)
}

// 数组下标: 0
// 数组下标: 1
// 数组下标: 2
// 数组下标: 3

values()

      values方法不传入任何参数,它返回一个数组的迭代对象,该对象包含数组的元素值(value)。可以用for...of... 进行循环

let arr = [1, 2, 3, 4]

for(let value of arr.values()) {
  console.log("数组元素:", value)
}

// 数组元素: 1
// 数组元素: 2
// 数组元素: 3
// 数组元素: 4

reduce()

reduce方法可以传入两个参数,第一个参数传入的是一个回调函数,回调函数里有四个参数,分别是:total,currentValue, currentIndex, array。

  • total:上一次累加的值

  • currentValue:当前的元素
  • currentIndex:当前元素的索引
  • array:当前元素所属的数组对象。

第二个参数传入的是一个初始值。

let arr = [1, 2, 3, 4, 5, 6];

let res = arr.reduce((preVal, curVal, curIndex, array) => {
  console.log('上一次累加的值:', preVal, "当前循环的数组元素的值:", curVal, "数组的下标:", curIndex, "原数组:", array)
  return preVal + curVal
}, 10);// 传递给函数的初始值

console.log('数组求和:', res)

// 上一次累加的值: 10 当前循环的数组元素的值: 1 数组的下标: 0 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 11 当前循环的数组元素的值: 2 数组的下标: 1 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 13 当前循环的数组元素的值: 3 数组的下标: 2 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 16 当前循环的数组元素的值: 4 数组的下标: 3 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 20 当前循环的数组元素的值: 5 数组的下标: 4 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 25 当前循环的数组元素的值: 6 数组的下标: 5 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 数组求和: 31

reduceRight()

      reduceRight方法的使用跟reduce方法的使用是一样的,只不过从后往前累加,看下面的代码就明白了。

let arr = [1, 2, 3, 4, 5, 6]

let res = arr.reduceRight((preVal, curVal, curIndex, array) => {
  console.log('上一次累加的值:', preVal, "当前循环的数组元素的值:", curVal, "数组的下标:", curIndex, "原数组:", array)
  return preVal + curVal
}, 10) // 传递给函数的初始值
console.log('数组求和:', res)

// 上一次累加的值: 10 当前循环的数组元素的值: 6 数组的下标: 5 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 16 当前循环的数组元素的值: 5 数组的下标: 4 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 21 当前循环的数组元素的值: 4 数组的下标: 3 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 25 当前循环的数组元素的值: 3 数组的下标: 2 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 28 当前循环的数组元素的值: 2 数组的下标: 1 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 上一次累加的值: 30 当前循环的数组元素的值: 1 数组的下标: 0 原数组: [ 1, 2, 3, 4, 5, 6 ]
// 数组求和: 31

数组的其他常用api

reverse()

      reverse方法的作用是颠倒数组中元素的顺序,该方法会改变原数组,不会生成新的数组,返回值是翻转后的数组。

let arr = [1, 2, 3, 4, 5, 6]

let res = arr.reverse()

console.log('翻转后的数组:', res, "原数组:", arr)
//   翻转后的数组: [ 6, 5, 4, 3, 2, 1 ] 原数组: [ 6, 5, 4, 3, 2, 1 ]

sort()

      sort可以用于数组的排序,能够将数组升序排序和降序排序,该方法会改变原数组,不会生成新的数组,返回值是翻转后的数组。

let arr = [1, 2, 8, 4, 5, 6]

let res1 = arr.sort((a, b) => { // 升序排序
  return a - b;
})
console.log("返回值:", res1, "原数组", arr)

let res2 = arr.sort((a, b) => { // 降序排序  
   return b - a;
})
console.log("返回值:", res2, "原数组", arr)

// 返回值: [ 1, 2, 4, 5, 6, 8 ] 原数组 [ 1, 2, 4, 5, 6, 8 ]
// 返回值: [ 8, 6, 5, 4, 2, 1 ] 原数组 [ 8, 6, 5, 4, 2, 1 ]

concat()

     concat 用于拼接元素,该方法可以传任意多个值,可以是具体的值,也可以是数组对象。返回值是一个新的数组。

let arr = [1]

let newArr = arr.concat(2, [3, 4], {name: '张三'}, false, undefined, null,'李四', '')

console.log('拼接后的数组:', newArr, "原数组", arr)
// 拼接后的数组: [ 1, 2, 3, 4, { name: '张三' }, false, undefined, null, '李四', '' ] 
// 原数组 [ 1 ]

slice() 

       slice 可从已有的数组中返回选定的元素。该方法可以传入两个值,两个值都是数组元素的下标值,第一参数表示元素选取的起始位置,第二个参数表示元素选取的结束位置。使用这个方法要记住,包头不包尾,什么意思呢? 看下面的代码。该方法会返回一个子数组。

let arr = [1, 2, 3, 4, 5, 5]

let subArr = arr.slice(1, 3);

console.log('子数组:', subArr, "原来的数组:", arr)
// 子数组: [ 2, 3 ] 原来的数组: [ 1, 2, 3, 4, 5, 5 ]

join()

      join方法可以将数组转化为一个字符串,并用指定的字符进行分割。该方法不会影响到原数组,返回值是一个字符创。

let arr = [1, 2, 3, 4, 5, 5]

let strArr = arr.join('--');

console.log('转化的字符串:', strArr, "原来的数组:", arr)
// 转化的字符串: 1--2--3--4--5--5 原来的数组: [ 1, 2, 3, 4, 5, 5 ]

数组的其他不常用api

isArray()

        isArray 方法可以判断一个值是否是数组。

let arr = [1, 2, 3, 4, 5, 5]

let isArray = Array.isArray(arr)

console.log('判断是否是数组:', isArray)
// 判断是否是数组: true
  • toString 和 toLocaleString

      isString 和 toLocaleString 方法可以将一个数组转化为字符串。

let arr = [1, 2, 3, 4, 5, 5]

let strArr1 = arr.toString()
let strArr2 = arr.toLocaleString()

console.log('数组转字符串: ', strArr1)
console.log('数组转字符串: ', strArr2)
// 数组转字符串:  1,2,3,4,5,5// 数组转字符串:  1,2,3,4,5,5

valueOf()

       返回 Array 对象的原始值。

let arr = [1, 2, 3, 4, 5, 5]

let res = arr.valueOf()

console.log('返回 arr 对象的原始值: ', res)
// 返回 arr 对象的原始值:  [ 1, 2, 3, 4, 5, 5 ]

你可能没用过的api

copyWithin()

      该方法可以将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。该方法可以传入3个参数。注意: IE 11 及更早版本不支持 copyWithin() 方法

  • target:要覆盖的起始位置
  • start:要复制的起始位置
  • end: 要复制的结束位置

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let res = arr.copyWithin(5, 0, 3)

console.log('返回值: ', res, "原数组:", arr)

// 返回值:  [ 1, 2, 3, 4,  5,1, 2, 3, 9, 10] 
// 原数组: [ 1, 2, 3, 4,  5,1, 2, 3, 9, 10]

fill()

       fill方法用于将一个固定值替换数组的元素,该方法可以传入三个参数。

  • value:要填充的值
  • start:要填充的起始位置
  • end:要填充的结束位置

开始填充和结束填充的位置要记住包头不包尾

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let res = arr.fill('--', 0, 2)

console.log('返回值: ', res)
console.log('原数组: ', arr)
// 返回值:  ['--', '--', 3, 4,  5,    6,    7, 8,  9, 10 ]
// 返回值:  ['--', '--', 3, 4,  5,    6,    7, 8,  9, 10 ]

       很尴尬,flat,flatMap,flatten这三个方法我百度了一下,有点懵,所以就先不说着三个函数的用法了。

总结

        以上数组的api的用法,是我通过百度和实践得出来的,因为篇幅实在太长了,很多api的用法其实没那么简单,有很多的奇技淫巧的,后面如果有机会会单独拎出来。总之,不断复盘,不断复盘,不断复盘。虽然花费的时间很多,但是这些都是基础,基础扎实,学什么都不虚。