javaScript ES5 ES6 数组方法总结(详解 + 最全)

280 阅读14分钟

前言

请说一下ES6新增数组的方法?作为前端开发面试题的高频问题,相信有很多人和我一样,虽然经常用,自己却不明白到底是ES5的方法,还是ES6的方法呢🤪?好吧,那就整理一下吧!于是便有了这篇文章。如有不正确的地方,还望各位小码哥不吝赐教。

images.jpeg

注:以下均为个人总结,资料参考MDN

正文

通过console.dir我们先对Array原型上所有方法进行查看。

    const arr = new Array()
    console.dir(arr)
image.png

🖕说明🖕

Array(callbackFn, thisAry),thisAry很少使用,在此暂不讨论thisAry参数的使用,示例如下

let arr = [1, 2, 3, 7, 9]
    let obj = {
      deelArr: items => {
        return items += 1
      }
    }
    // arr.forEach(item => {
    //   console.log(this)
    //   剪头函数没有自己的this,指向window
    //   console.log(this.deelArr(item))
    //   window上并没有deelArr方法,报错> this.deelArr1 is not a function
    // }, obj)
    arr.forEach(function(item) {
      console.log(this === obj) // true
      console.log(this.deelArr(item))
    }, obj)
image.png

ES5

不改变原数组的方法

forEach

作用: 对数组的每个元素执行一次给定的函数。
返回值:undefined。
callbackFn参数:forEach(callbackFn(item, index, self))
  参数1/item: 当前处理的元素;
  参数2/index: 当前处理元素的下标;
  参数3/self: 当前数组;

let arr = [1, 2, 3]
arr.forEach((item, index, self) => {
  console.log('[item]:', item, '[index]:', index, '[self]:', self)
  // do something
})
// [item]: 1 [index]: 0 [self]: (3) [1, 2, 3]
// [item]: 2 [index]: 1 [self]: (3) [1, 2, 3]
// [item]: 3 [index]: 2 [self]: (3) [1, 2, 3]

indexOf

lastIndexOf 同上indexOf,区别在于最后一次出现指定元素的位置

作用:返回数组中第一次出现给定元素的下标,如果不存在则返回 -1。
返回值:第一个匹配元素的下标 or -1。
参数
  参数1: 数组中要查找的元素;
  参数2: 开始搜索的索引(默认从零开始)。

let arr = [1, 2, 3, 5, 3, 9, 10]
let arrResult1 = arr.indexOf(3, 2)
let arrResult2 = arr.indexOf(3, 3)
let arrResult3 = arr.indexOf(3, 5)
console.log('[arrResult1]:', arrResult1)
console.log('[arrResult2]:', arrResult2)
console.log('[arrResult3]:', arrResult3)
// [arrResult1]: 2
// [arrResult2]: 4
// [arrResult3]: -1

slice

作用:返回一个新的数组对象,是原数组下标 参数1 至 参数2组成的新数组(包括 参数1 ,不包括参数2)。
返回值:新的数组对象。
参数
  参数1: 提取起始处的索引(从 0 开始);
  参数2: 提取终止处的索引(从 0 开始);
⚠️注意⚠️截取的新数组包含起始下标,但不包含终止索引

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.slice(2, 3)
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] [3]

filter

作用:过滤出满足给定条件的所有元素,并保存在结果数组中。
返回值:包含满足条件的所有元素的数组。
callbackFn参数:forEach(callbackFn(item, index, self))
  参数1/item: 当前处理的元素;
  参数2/index: 当前处理元素的下标;
  参数3/self: 当前数组;

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.filter((item, index) => {
    return item >= 3
})
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] (3) [3, 7, 9]

every

作用:测试一个数组内的所有元素是否都能通过指定函数的测试。
返回值:Boolean(只要有一个元素不满足就返回false)。
参数:用于测试元素的回调函数callbackFn。

let arr = [1, 2, 3, 7, 9]
let arrFalseResult = arr.every(item => {
    return item >= 3
})
let arrTrueResult = arr.every(item => {
    return item >= 1
})
console.log('[arr]', arr)
console.log('[arrFalseResult]', arrFalseResult)
console.log('[arrTrueResult]', arrTrueResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrFalseResult] false
// [arrTrueResult] true

some

作用:与every相似,测试数组中是否至少有一个元素通过了由提供的函数实现的测试。
返回值:Boolean(只要有一个元素满足就返回true)。
参数:用于测试元素的回调函数callbackFn。

let arr = [1, 2, 3, 7, 9]
let arrFalseResult = arr.some(item => {
    return item > 9
})
let arrTrueResult = arr.some(item => {
    return item >= 9
})
console.log('[arr]', arr)
console.log('[arrFalseResult]', arrFalseResult)
console.log('[arrTrueResult]', arrTrueResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrFalseResult] false
// [arrTrueResult] true

reduce

reduceRight 同reduce,区别在于从右向左遍历累加

作用:测试一个数组内的所有元素是否都能通过指定函数的测试。
返回值:Boolean(只要有一个元素不满足就返回false)。
参数:reduce(callbackFn(参数1,参数2), initialValue)
  参数1: 上一次累加的值,第一次遍历为initialValue的值;
  参数2: 当前元素的值;
  initialValue: 作为第一次遍历参数1的值;

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.reduce((pre, cur) => {
    return pre + cur
}, 0)
console.log('[arrResult]', arrResult)
// [arrResult] 22
let personList = [
  {
    name: '李青',
    money: 4800
  },
  {
    name: '卡兹克',
    money: 6300
  },
  {
    name: 'VN',
    money: 6300
  }
]
let sumMoney = personList.reduce((pre, cur) => {
    return pre + cur.money
}, 0)
console.log('[sumMoney]', sumMoney)
// [sumMoney] 17400

join

作用:将所有元素连接成一个字符串并返回这个字符串,用逗号或指定的分隔符字符串分隔。如果数组只有一个元素,那么将返回该元素而不使用分隔符。
返回值:所有数组元素连接的字符串。
参数:用于连接所有元素的字符串(默认是",")

let arr = [1, 2, 3, 7, 9]
let arrResult1 = arr.join()
let arrResult2 = arr.join('=')
let emptyArr = []
let emptyArrResult = emptyArr.join()
let LengthIsOneArr = [1]
let LengthIsOneArrResult = LengthIsOneArr.join()
console.log('[arr]', arr) // 默认逗号连接
console.log('[arrResult1]', arrResult1) // 默认逗号连接
console.log('[arrResult2]', arrResult2) // 参数=进行连接
console.log('[emptyArrResult]', emptyArrResult) // length为0,输出空字符串
console.log('[arr1Result]', LengthIsOneArrResult) // length为1,省略连接符
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult1] 1,2,3,7,9
// [arrResult2] 1=2=3=7=9
// [emptyArrResult] 
// [arr1Result] 1

concat

作用:合并两个或多个数组。
返回值:合并后的新数组。
参数:concat(value0, value1, /* … ,*/ valueN)
  参数0-n: 用于合并到原数组的数组/值;

let arr = [1, 2, 3, 7, 9]
let arr1 = ['李青', '卡兹克', 'VN']
let arrResult = arr.concat(arr1, ['一库', '哈撒剋?'], '坚如磐石')
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] (10) [1, 2, 3, 7, 9, '李青', '卡兹克', 'VN', '一库', '哈撒剋?', '坚如磐石']

toString

作用:将数组转换为字符串。
返回值:返回一个字符串。
参数:无

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.toString()
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] 1,2,3,7,9

isArray

作用:用于确定传递的值是否是一个 Array
返回值:Boolean。
参数:Array.isArray(value)
  参数/value: 需要确定的数据

let arr = [1, 2, 3, 7, 9]
let str = 'Hope it is still there'
let arrResult = Array.isArray(arr)
let strResult = Array.isArray(str)
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
console.log('[strResult]', strResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] true
// [strResult] false

map

作用:创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
返回值:每个元素都是回调函数的返回值组成的新数组。
参数:map(callbackFn(item, index, self))
  参数1/item: 当前处理的元素;
  参数2/index: 当前处理元素的下标;
  参数3/self: 当前数组;

let arr = [1, 3, 7]
let arrResult = arr.map(item => {
        return item = item + 1
})
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] [arr] (3) [1, 3, 7]
// [arrResult] (3) [2, 4, 8]

改变原数组的方法

splice

toSpliced 同splice,区别在于不改变原数组,返回一个新的数组

作用移除或者替换已存在的元素和/或添加新元素改变一个数组的内容。
返回值:截取的数组,如果参数2为0,返回一个空数组。
参数:splice(start, end, item1, item2, itemN)
  参数1/start: 开始改变数组的位置;
  参数2/end: 数组中从 参数1 开始删除的元素数量;
  参数item1-itemN: 从 参数1 开始要加入到数组中的元素;

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.splice(1, 1, 'tom', 'jack')
// 从下标1开始截取1个返回,并把原数组截取的部分替换为'tom', 'jack'
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] [1, 'tom', 'jack', 3, 7, 9]
// [arrResult] [2]

reverse

toReversed 同reverse,区别在于不改变原数组,返回一个新的数组

作用:数组中的元素顺序将被翻转,变为与之前相反的方向。
返回值:翻转后的原数组。
参数:无

let arr = [1, 2, 3, 7, 9]
arr.reverse()
console.log('[arr]', arr)
// [arr] (5) [9, 7, 3, 2, 1]

sort

toSorted 同sort,区别在于不改变原数组,返回一个新的数组

作用:对数组的元素进行排序
返回值:进行排序后的原数组。
无参数时:元素转换为字符串(或者当元素有一个为字符串时),然后按照它们的 UTF-16 码元值升序排序
有参数时:callbackFn(a, b)
  参数1/a: 第一个用于比较的元素;
  参数2/b: 第二个用于比较的元素;

let arr = [1, 9, 3, 2, 7, 10000]
arr.sort()
// 如果省略回调函数,元素会被转换为字符串,然后根据每个字符的 Unicode 码位值进行排序
console.log('[arr]', arr)
let arr1 = [1, 9, 3, 2, 7, 10000]
arr1.sort((a, b) => {
  // return b - a // 降序
  return a - b // 升序
})
console.log('[arr1]', arr1)
// [arr] (6) [1, 10000, 2, 3, 7, 9]
// [arr1] (6) [1, 2, 3, 7, 9, 10000]

push

作用:从数组最后一项添加元素。
返回值:添加新元素后的数组的length。
参数:push(element0, element1, /* … ,*/ elementN)
  参数element0-elementN: 用于添加到原数组的元素;

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.push(['任意值'], '那么在天音波滑行的途中')
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (7) [1, 2, 3, 7, 9, Array(1), '那么在天音波滑行的途中']
// [arrResult] 7

pop

作用:从数组最后一项删除元素。
返回值:删除的元素(如果数组为空则返回 undefined)。
参数:无

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.pop()
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (4) [1, 2, 3, 7]
// [arrResult] 9

unshift

作用:从数组第一项添加元素。
返回值:添加新元素后的数组的length。
参数:unshift(element0, element1, /* … ,*/ elementN)
  参数element0-elementN: 用于添加到原数组的元素;

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.unshift(['任意值'], '那么在天音波滑行的途中')
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (7) [Array(1), '那么在天音波滑行的途中', 1, 2, 3, 7, 9]
// [arrResult] 7

shift

作用:从数组第一项删除元素。
返回值:删除的元素(如果数组为空则返回 undefined)。
参数:无

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.shift()
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (4) [2, 3, 7, 9]
// [arrResult] 1

ES6 +

includes

作用:判断一个数组是否包含一个指定的值。
返回值:Boolean。
参数:includes(searchElement, fromIndex)用于判断的值
  参数searchElement: 用于判断的值;
  参数fromIndex: 开始搜索的索引(从零开始);

1.负索引从数组末尾开始计数——如果 fromIndex < 0,那么实际使用的是 fromIndex + array.length。然而在这种情况下,数组仍然从前往后进行搜索。
2.如果 fromIndex < -array.length 或者省略 fromIndex,则使用 0,这将导致整个数组被搜索。
3.如果 fromIndex >= array.length,则不会搜索数组并返回 false

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.includes(3, 3)
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] false

find

findLast 同find,区别在于逆向迭代

作用:遍历数组,找出满足条件的元素。
返回值:数组中第一个满足所提供测试函数的元素的值,否则返回 undefined
参数:用于测试元素的回调函数callbackFn

let personList = [
    {
        name: '李青',
        money: 4800
    },
    {
        name: '卡兹克',
        money: 6300
    },
    {
        name: 'VN',
        money: 6300
    }
]
let personResult = personList.find(item => {
    return item.name === '李青'
})
let personResult1 = personList.find(item => {
    return item.name === '古拉加斯'
})
console.log('[personResult]', personResult)
console.log('[personResult1]', personResult1)
// [personResult] {name: '李青', money: 4800}
// [personResult1] undefined

findIndex

findLastIndex 同findIndex,区别在于逆向迭代

作用:找出数组中满足条件的第一个元素的索引。
返回值:第一个满足条件的索引。否则返回 -1
参数:用于测试元素的回调函数callbackFn

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.findIndex(item => {
    return item > 3
})
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (6) [1, 2, 3, 7, 9, 3]
// [arrResult] 3

flat

作用扁平化,创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中。
返回值:包含拼接后的子数组元素的新数组。
参数:flat(depth)
  参数depth: 提取嵌套数组的结构深度,默认值为 1;

let arr = [1, 2, 3, [[7, 9]]]
let arr1 = [1, 2, 3, [[[7, 9]]]]
let arrResult = arr.flat()
let arrResult1 = arr1.flat(3)
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
console.log('[arrResult]1', arrResult1)
// [arr] (4) [1, 2, 3, [[7, 9]]]
// [arrResult] (4) [1, 2, 3, [7, 9]]
// [arrResult]1 (5) [1, 2, 3, 7, 9]

flatMap

作用:等价于在调用 map() 方法后再调用深度为 1 的 flat()方法
返回值:新的数组,其中每个元素都是回调函数的结果,并且被展开一级
参数:用于测试元素的回调函数callbackFn

let arr = [1, 2, 3, 7, 9]
let arrResult = arr.flatMap(item => {
    if (item === 3) {
        return [[6, 6, 6]]
    } else {
        return '不等于3'
    }
})
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (5) [1, 2, 3, 7, 9]
// [arrResult] (5) ['不等于3', '不等于3', [6, 6, 6], '不等于3', '不等于3']0: "不等于3"1: "不等于3"2: (3) [6, 6, 6]3: "不等于3"4: "不等于3"length: 5[[Prototype]]: Array(0)

copywithin

作用:复制数组的一部分到同一数组中的另一个位置,并返回,不会改变原数组的长度(替换会从开始位置向后移动)。
返回值:改变后的原数组。
参数:callbackFn(target, start, end)
  参数1/target: 开始替换的目标位置;
  参数2/start: 要复制元素的起始位置(包含);
  参数3/end: 要复制元素的结束位置(不包含);

let arr = [1, 2, 3, 5, 7, 9]
let arrResult = arr.copyWithin(1, 2, 5)
console.log('[arr]', arr)
console.log('[arrResult]', arrResult)
// [arr] (6) [1, 3, 5, 7, 7, 9]
// [arrResult] (6) [1, 3, 5, 7, 7, 9]

fill

作用:填充数组元素的值。
返回值:经 value 填充修改后的原数组。
参数:callbackFn(value, start, end)
  参数1/value: 用来填充数组元素的值;
  参数2/start: 开始填充的索引;

  • 负数索引从数组的末端开始计算,如果 start < 0,则使用 start + array.length
  • 如果 start < -array.length 或 start 被省略,则使用 0
  • 如果 start >= array.length,没有索引被填充。

  参数3/end: 结束填充的索引(不包含);

  • 负数索引从数组的末端开始计算,如果 end < 0,则使用 end + array.length
  • 如果 end < -array.length,则使用 0
  • 如果 end >= array.length 或 end 被省略,则使用 array.length,导致所有索引都被填充。
  • 如果经标准化后,end 的位置在 start 之前或之上,没有索引被填充。
console.log([1, 2, 3].fill(4)); // [4, 4, 4]
console.log([1, 2, 3].fill(4, 1)); // [1, 4, 4]
console.log([1, 2, 3].fill(4, 1, 2)); // [1, 4, 3]
console.log([1, 2, 3].fill(4, 1, 1)); // [1, 2, 3]
console.log([1, 2, 3].fill(4, 3, 3)); // [1, 2, 3]
console.log([1, 2, 3].fill(4, -3, -2)); // [4, 2, 3]
console.log([1, 2, 3].fill(4, NaN, NaN)); // [1, 2, 3]
console.log([1, 2, 3].fill(4, 3, 5)); // [1, 2, 3]
console.log(Array(3).fill(4)); // [4, 4, 4]

补充:使用fill创建矩阵

const arr = new Array(3);
for (let i = 0; i < arr.length; i++) {
    // 对创建长度为3的数组arr,赋值每项都为长度为3的数组,且复制的数组全部填充3
    arr[i] = new Array(3).fill(3);
}
console.log(arr)
image.png

Array.from

作用:将一个类数组或可迭代对象,创建成一个新的浅拷贝的数组实例。
返回值:新数组。
参数:Array.from(arrayLike, mapFn, thisArg)
  arrayLike: 想要转换成数组的类数组或可迭代对象;
  mapFn: 调用数组每个元素的函数(可选);

let obj = {
    0: '李青',
    1: '内瑟斯',
    length: 2
}
let arr = Array.from(obj)
let arr1 = Array.from(obj, item => 'name:' + item)
console.log('[arr]', arr)
console.log('[arr1]', arr1)
// [arr] (2) ['李青', '内瑟斯']
// [arr1] (2) ['name:李青', 'name:内瑟斯']

Array.of

与new Array()的区别在于参数长度为1的时候:
1.new Array(n)是创建长度为n的空数组;
2.Array.of(n)则是创建[n]

作用:在不考虑参数数量类型的情况下,创建一个新的数组。
返回值:创建的新数组。
参数:Array.of(element0, element1, /* … ,*/ elementN)

console.log(Array.of(3)) // [3]
console.log(new Array(3)) // [empty × 3]
console.log(Array.of(3, 6, 9)) // [3, 6, 9]
console.log(new Array(3, 6, 9)) // [3, 6, 9]

keys

作用:返回一个新的数组迭代器对象,其中包含数组中每个索引的键,在稀疏数组中keys() 迭代器不会忽略缺失属性的键。
返回值数组迭代器对象。
参数:无

let arr = [1, 3, , 7]
let iterator = arr.keys()
console.log('[iterator]', iterator)
for (const key of iterator) {
    console.log('[key]', key)
}
// [iterator] Array Iterator {}
// [key] 0
// [key] 1
// [key] 2
// [key] 3

values

keys类似,也是返回一个新的数组迭代器对象,区别在于
1.keys数组迭代器对象,其中包含的是数组中每个索引的键
2.values数组迭代器对象,其中包含的是数组中每个元素的值,空值输出undefined

作用:返回一个新的数组迭代器对象,其中包含数组中每个元素的值,在稀疏数组中values() 迭代器把空值输出undefined
返回值数组迭代器对象。
参数:无

let arr = [1, 3, , 7]
let iterator = arr.values()
console.log('[iterator]', iterator)
for (const key of iterator) {
    console.log('[key]', key)
}
// [iterator] Array Iterator {}
// [key] 1
// [key] 3
// [key] undefined
// [key] 7

entries

可以理解为keys与values的结合体,它包含的是数组中每个索引的键/值对

作用:返回一个新的数组迭代器对象,该对象包含数组中每个索引的键/值对
返回值数组迭代器对象。
参数:无

let arr = [1, 3, , 7]
let iterator = arr.entries()
console.log('[iterator]', iterator)
for (const key of iterator) {
    console.log('[key]', key)
}
// [iterator] Array Iterator {}
// [key] (2) [0, 1]
// [key] (2) [1, 3]
// [key] (2) [2, undefined]
// [key] (2) [3, 7]