跳到主要内容

数组方法

注意:

  • 有的方法会修改调用他们的数组,而有些不会。
  • 也有几个方法返回数组
    • 有时候返回这个数组的新数组,原始数组不变。
    • 有时候返回数组会被修改,返回的是被修改后的数组引用。

几个数组方法

  • 迭代器方法:用于遍历数组元素,通常会对每个元素调用一次我们指定的函数。
  • 栈和队列方法:用于在开头或末尾向数组中添加元素或从数组中删除元素。
  • 子数组方法:用于提取、删除、插入、填充和复制更大数组的连接区域。
  • 搜索和排序方法:用于在数组中查找元素和对数组元素排序。

数组迭代器方法

数组迭代器方法:会按照顺序把数组的每个元素传给我们提供的函数,可便于对数组进行迭代、映射、过滤、测试和归并。

  • 这组方法:都接收一个函数作为第一个参数。
  • 并对每个数组的元素都调用一次这个函数。
  • 通常我们提供的这个函数被调用是都会收到 3 个参数,
      1. 数组元素的值;
      1. 数组元素的索引;
      1. 数组本身;
  • 通常我们只需要这几个参数中的第一个,可以忽略第二和第三个值。

forEach() 遍历循环,无返回值

遍历循环数组。

let data = [1, 2, 3, 4, 5],
sum = 0
// 计算数组元素之和
data.forEach((value) => {
sum += value
})

// 递增每个元素的值
data.forEach(function (v, i, a) {
a[i] = v + 1
})
console.log(data) // => [2,3,4,5,6]

map() 返回的是新数组

遍历循环,有返回值,返回的是新数组。

let a = [1, 2, 3]
a.map((x = x * x)) // 返回新数组[1,4,9]

filter() 过滤内容

filter()方法返回一个数组,该数组包含调用它的数组的子数组。

  • 传给这个方法的函数应该是断言函数。
filter() 不改变原数组,始终返回新数组。
let b = [5, 4, 3, 2, 1]
console.log(b.filter((x) => x < 3)) // [2,1]
console.log(b.filter((x, i) => i % 2 === 0)) // [5,3,1]
console.log('b', b) //  [5, 4, 3, 2, 1]
  • filter() 会跳过稀疏数组中缺失的元素,它返回的数组始终是周密的。
使用filter(),清理掉稀疏数组中的空隙
a = a.filter(() => true)
清空空缝,又想删除值为undefined和null的元素
a = a.filter((x) => x !== undefined && x !== null)

find() 和 findIndex()

find() 和 findIndex()方法与 filter()类似,表现在他们都是遍历数组,寻找断言函数返回真值的元素。 和 filter()不同的是,这两个方法会在断言函数找到第一个元素后停止迭代。

  • find() 返回匹配的元素。没有找到返回 undefined
  • findIndex() 返回匹配的元素的索引。没有找到返回-1
let a = [1, 2, 3, 4, 5]
a.findIndex((x) => x === 3) // => 2,值为3的索引是2
a.findIndex((x) => x < 0) // => -1.数组中没有负数
a.find((x) => x % 5 === 0) // =>5: 5的倍数
a.find((x) => x % 7 === 0) // undefined: 数组中没有7的倍数。

every() 要全部真 和 some() 只要一个真就是真

every() 和 some()方法是数组断言方法,即它们会对数组元素调用我们传入的断言函数,最后返回 true 或 false.

  • every() 会在断言函数对数组的所有元素都返回 true 是返回 true。
  • some() 只要数组元素中有一个让断言函数返回 true 它就返回 true,但需要所有都 false,才返回 false。
  • 如果在空数组[]调用他们,按照数学的传统,every 返回 true,some()返回 false
let a = [1, 2, 3, 4, 5]
a.some((x) => x % 2 === 0) // => true
a.smoe(isNaN) // => false

reduce() 与 reduceRight()

  • reduce() 和 reduceRight()方法使用我们指定的函数归并数组元素,最终产生一个值。
  • 在函数编程中,归并是一个常见的操作,有时候也称为注入(inject)或折叠(fold)。看例子更好理解
let c = [1, 2, 3, 4, 5]
c.reduce((x, y) => x + y, 0) // => 15; 所有值之和
c.reduce((x, y) => x * y, 1) // => 120;所有值之积
c.reduce((x, y) => (x > y ? x : y)) // => 5,最大值

flat() 和 flatMap() 打平数组

  • 在 ES2019 中,flat()方法用于创建并返回一个新数组。
  • 这个新数组包含与它调用 flat()的数组相同的元素,
  • 只不过其中任何本身也是数组的元素会被“打平”填充到返回的数组中。
flat(打平深度),打平深度默认1
const flatArr1 = [1, [2, 3]].flat() // => [1, 2, 3]
const flatArr2 = [1, [2, [3]]].flat() // => [1, 2, [3]]
const flatArr3 = [1, [2, [3]]].flat(2) // => [1, 2, 3]
console.log('flatArr1', flatArr1)
console.log('flatArr2', flatArr2)
console.log('flatArr3', flatArr3)
  • flatMap()方法与 map()方法相似,只不过返回的数组会自动被打平,就是传给了 flat()一样。
  • 调用 a.flatMap(f) 等同于(但效率远高于) a.map(f).flat()。
let phrases = ['hello world', 'the definitive guide']
let words = phrases.flatMap((phrase) => phrase.split(' '))
console.log(words) //  ['hello', 'world', 'the', 'definitive', 'guide']

concat() 添加数组

  • concat()方法创建并返回一个新数组。
  • concat()参数可以是数组元素,也可以是数组本身。但都是进行连接将原有的数组与参数元素进行连接。
  • 如果参数里面是嵌套多层数组,并不会打平数组。
  • 原数组不变

可能有性能问题:

  • concat()会创建调用它的数组的副本,这样代价有点大。
  • 如果正在使用 concat(),如果 push()或 splice()方法可以替代 concat()就进行替代。
let concatArr = [1, 2, 3]
console.log(concatArr.concat(4, 5)) // => 返回新数组[1, 2, 3, 4, 5]
console.log(concatArr.concat([4, 5], [6, 7])) // => 返回新数组[1, 2, 3, 4, 5, 6, 7]
console.log(concatArr.concat(4, [5, [6, 7]])) // => 返回新数组[1, 2, 3, 4, 5, Array(2)]
console.log(concatArr) // =>[1, 2, 3] 原数组不变

通过 push()、pop()、shift()、和 unshift()、实现栈和队列操作

都会就地修改原数组。

  • push():在数组末尾追加元素,返回数组新长度。
  • pop():删除数组尾部一个元素,返回删除的值。
  • unshift():在数组首部添加元素,返回数组新长度。
  • shift():在数组首部删除一个元素,返回删除的值。

先入后出的栈

组合使用push()和pop(),实现数组先入后出的栈
let stack = []
stack.push(1, 2)
console.log(stack) // => [1, 2]
stack.pop()
console.log(stack) // => [1]
stack.push(3)
console.log(stack) // => [1, 3]
stack.pop()
console.log(stack) // => [1]
stack.push([4, 5])
console.log(stack) // =>[1, Array(2)]
stack.pop()
console.log(stack) // => [1]
stack.pop()
console.log(stack) // => []

使用 push()和 shift()实现队列

使用push()和shift()实现队列
let q = []
q.push(1, 2)
console.log(q) // => [1,2]
q.shift()
console.log(q) // => [2]
q.push(3)
console.log(q) // => [2,3]
q.shift()
console.log(q) // => [3]
q.shift()
console.log(q) // => []

unshift()和 shift 实现的栈,效率不如 push()和 pop(),因为每次在数组开通添加或者删除元素都要向上或向下移动元素。

使用 slice()、splice()、fill()、和 copyWithin()

翻译:

  • slice :片,薄片,部分
  • splice:粘接,粘接(胶片、磁带等);绞接(两段绳子);捻接
  • fill:填满;充满…的;(使)充满;填补(洞、孔);
  • copyWithin:复制范围

slice()

  • 不改变原数组,复制部分数组元素出来。
  • slice() 方法返回一个数组的切片或者子数组。 Array.prototype.slice() 是 JavaScript 中的一个数组方法,它用于从原始数组中提取一个或多个元素,并返回一个新的数组,这个新数组包含了原始数组中指定索引范围内的元素。slice() 方法不会改变原始数组。

语法:

arr.slice([begin[, end]])
  • begin: 可选参数,表示要提取子数组的第一个元素的索引(包含)。默认值为 0,即从数组的开始位置提取。
  • end: 可选参数,表示要提取子数组最后一个元素之后的位置(不包含)。如果省略,则会一直提取到数组末尾。

示例与行为说明:

  1. 不传入任何参数时,slice() 会返回整个原数组的新副本:

    let original = [1, 2, 3, 4, 5]
    let copy = original.slice()
    console.log(copy) // 输出: [1, 2, 3, 4, 5]
  2. 提供一个起始索引:

    let array = ['a', 'b', 'c', 'd', 'e']
    let subarray = array.slice(1)
    console.log(subarray) // 输出: ['b', 'c', 'd', 'e']
  3. 提供起始和结束索引:

    let numbers = [10, 20, 30, 40, 50]
    let slicedNumbers = numbers.slice(1, 3)
    console.log(slicedNumbers) // 输出: [20, 30]
  4. 当索引是负数时,它们会被解释为相对于数组末尾的偏移量:

    let fruits = ['apple', 'banana', 'cherry', 'date']
    let lastTwoFruits = fruits.slice(-2)
    console.log(lastTwoFruits) // 输出: ['cherry', 'date']

slice() 方法的核心功能是从给定的起点(包括)到终点(不包括)创建并返回一个源数组的部分副本。如果你需要截取数组的一部分而不影响原数组,slice() 就是一个非常有用的工具。

splice()

会改变原数组,删除、插入、替换数组元素

  • Array.prototype.splice() 是 JavaScript 中的一个数组方法,
  • 用于直接在原数组上进行删除、插入和替换操作。
  • 它会改变原始数组,并返回一个包含被删除元素的新数组。

语法:

array.splice(start, deleteCount[, item1, item2, ...])

参数说明:

  • start: 必需,整数类型,指定要修改的开始位置(索引)。
    • 如果 start 是负数,则表示从数组结尾往前计算的位置,即 -1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
  • deleteCount: 可选,整数类型,表示要移除的元素数量。
    • 如果省略或者设置为 0,则不会删除任何元素,但可以继续添加新元素。
    • 如果 deleteCount 大于 start 后面的元素个数,则会移除从 start 开始到数组末尾的所有元素。
  • item1, item2, ...: 可选,要在删除元素后插入的新元素,可以是任意多个。

功能说明:

  • 删除:根据 deleteCount 参数指定的数量从 start 索引处开始删除元素。
  • 插入:如果提供了额外的参数(新元素),它们将被插入到 start 索引处,之后的元素会被向右移动(如果有的话)。
  • 替换:当同时设置了 deleteCount 和新元素时,splice() 方法首先删除指定数量的元素,然后在其位置插入新元素,从而实现了替换效果。

示例:

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

// 删除操作
arr.splice(1, 2) // 删除索引 1 开始的两个元素
console.log(arr) // 输出: [1, 4, 5]

// 插入操作
arr.splice(1, 0, 'a', 'b') // 在索引 1 处插入 'a' 和 'b'
console.log(arr) // 输出: [1, "a", "b", 4, 5]

// 替换操作
arr.splice(2, 2, 'x', 'y') // 删除索引 2 开始的两个元素,并插入 'x' 和 'y'
console.log(arr) // 输出: [1, "a", "x", "y", 5]
  • 所以 splice() 方法是一个非常强大的工具,允许你在数组的特定位置一次性完成多种操作,如删除、插入或替换元素。
  • 并且由于它是原地修改数组的方法,因此不需要额外创建新的数组来存储结果。

fill()

  • fill()方法将数组的元素或切片设置为指定的值。
  • 它会修改调用它的数组,返回修改后的数组。
  • 第一个参数是要设置的值。
  • 第二个参数是指定起始索引。(可选)
  • 第三个参数是指定终止索引。(可选)
let a = new Array(5)
a.fill(0)
a.fill(9, 1)
a.fill(8, 2, -1)

copyWithin()

Array.prototype.copyWithin() 是 JavaScript ES6 引入的一个数组实例方法,它允许你复制数组内部的一部分到同一数组中的另一个位置,并覆盖原有元素。这个方法不会改变数组的长度,只是在原数组范围内重新排列元素。

语法:

arr.copyWithin(target, (start = 0), (end = this.length))
  • target: 必需,整数,表示要将复制的元素插入的目标起始索引位置。
  • start: 可选,整数,默认为 0,表示复制元素的起始索引位置。
  • end: 可选,整数,默认为数组的长度(this.length),表示复制元素的结束索引位置(不包含该位置的元素)。

startend 指定的是负数时,它们会被解释为从数组末尾开始计算的位置,即 -1 表示最后一个元素,-2 表示倒数第二个元素,以此类推。

示例:

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

// 将数组的前两个元素复制到索引2及其之后的位置
array.copyWithin(2, 0, 2)
console.log(array) // 输出: [1, 2, 1, 2, 5]

// 把数组的最后三个元素复制到开头
array.copyWithin(0, -3)
console.log(array) // 输出: [4, 5, 1, 2, 5]

sort()

JavaScript 中的 Array.prototype.sort() 方法是用来对数组元素进行排序的方法。默认情况下,sort() 会按照字符串 Unicode 码点顺序对数组元素进行排序,这意味着对于数字组成的数组,如果不自定义比较函数,可能会得到不符合预期的结果。

基本语法:

array.sort([compareFunction])
  • compareFunction: 可选参数,是一个用于指定排序顺序的函数。这个函数接受两个参数(当前正在比较的元素),并返回一个整数:
    • 如果返回值小于 0,则表示第一个元素应该位于第二个元素之前。
    • 如果返回值等于 0,则两个元素位置不变。
    • 如果返回值大于 0,则表示第一个元素应该位于第二个元素之后。

例如:

// 默认排序(按字符顺序)
let numbers = [40, 10, 100, 5, 1]
numbers.sort() // 输出: [1, 10, 100, 40, 5] (注意,数字被当作字符串处理)

// 自定义排序(升序排列数字)
numbers.sort(function (a, b) {
return a - b
})
console.log(numbers) // 输出: [1, 5, 10, 40, 100] (现在是按数字大小正确排序了)

// 或者使用箭头函数简化写法
numbers.sort((a, b) => a - b)
console.log(numbers) // 输出: [1, 5, 10, 40, 100]

在自定义比较函数中,你可以根据实际需求来决定元素之间的排序逻辑。这对于需要对复杂数据类型(如对象)的数组进行排序时尤其有用,因为在这种情况下可以依据对象中的某个属性或多个属性来进行排序。

reverse() 反转数组

对原数组直接进行反转

let a = [1, 2, 3]
a.reverse() // =>[3,2,1]

数组到字符串的转换

Array 类定义了 3 个把数组转换成字符串的方法。

  • 通常可以用在记录日志或错误消息的时候。

如果想把数组的文本内容保存起来以备用后,可以使用 JSON.stringify()方法对数组执行序列化,而不是使用这里介绍的方法。

join()数组转字符串

  • join()方法把数组的所有元素转换为字符串,然后把它们拼接起来并返回结果字符串。
  • 可以提供一个分割符参数(可选)
  • 没提供,默认为,逗号。
  • join()方法执行的是 String.split()方法的反向操作。
  • String.split()是分割字符串成数组。
let a = [1, 2, 3]
a.join() // =>“1,2,3”
a.join(' ') // => "1 2 3"
a.join('') // =>"123"
let b = new Array(10)
b.join('-') // => "----------"; 包含9个链接字符的字符串

toString()

使用数组 toString()方法,将数组转换成字符串

;[1, 2, 3]
.toString() // => "1,2,3"
[('a', 'b', 'c')].toString() // => "a,b,c"
[(1, [2, 'c'])].toString() // =>"1,2,c"

还有 toClocaleString()方法也可以

静态数组函数

Array 数组定义了 3 个静态方法。可以通过 Array 构造函数而非数组调用。

  1. Array.of()
  2. Array.from()
  3. Array.isArray()
判断是否是数组
Array.isArray([]) // => true
Array.isArray({}) // => false

类数组对象

测试对象是不是类数组对象
function isArrayLike(o) {
if (
o &&
typeof o === 'object' &&
Number.isFinite(o.length) &&
o.length >= 0 &&
Number.isInteger(o.length) &&
o.length < 4294967295
) {
return true
} else {
return false
}
}

Number.isFinite()

Number.isFinite() 是 JavaScript 中的一个全局方法,用于判断给定的值是否为有限数值(finite number)。它属于 Number 对象的方法,可以用来区分正常的数字与特殊值(如 Infinity-InfinityNaN)。

基本语法:

Number.isFinite(value)
  • value: 必需,要检测的值。

该方法返回一个布尔值:

  • 如果参数是一个有限数值,则返回 true
  • 如果参数是 Infinity-InfinityNaN 或非数字类型(例如字符串、null、undefined 等),则返回 false

示例:

console.log(Number.isFinite(10)) // true,因为 10 是有限数
console.log(Number.isFinite(0)) // true,因为 0 也是有限数

console.log(Number.isFinite(-Infinity)) // false,因为 -Infinity 不是有限数
console.log(Number.isFinite(Infinity)) // false,因为 Infinity 也不是有限数
console.log(Number.isFinite(NaN)) // false,因为 NaN 不是有限数

console.log(Number.isFinite('10')) // false,因为 "10" 是字符串而不是有限数
console.log(Number.isFinite(null)) // false,因为 null 不是有限数

Number.isFinite() 方法对于数据验证和处理可能存在的无穷大或非数字值的情况非常有用。在需要确保操作的是有效且有限的数字时,它可以提供方便的检测手段。

Number.isInteger()

Number.isInteger() 是 JavaScript 中的一个全局方法,属于 Number 对象的方法,用于判断给定的值是否为整数。

基本语法:

Number.isInteger(value)
  • value: 必需,要检测的值。

该方法返回一个布尔值:

  • 如果参数是一个整数(包括正负无穷大),则返回 true
  • 如果参数是浮点数、NaNInfinity-Infinity 或非数字类型(例如字符串、null、undefined 等),则返回 false

示例:

console.log(Number.isInteger(10)) // true,因为 10 是整数
console.log(Number.isInteger(-10)) // true,因为 -10 也是整数

console.log(Number.isInteger(10.5)) // false,因为 10.5 是浮点数
console.log(Number.isInteger(NaN)) // false,因为 NaN 不是整数
console.log(Number.isInteger(Infinity)) // false,因为 Infinity 不是整数
console.log(Number.isInteger('10')) // false,因为 "10" 是字符串而不是整数
console.log(Number.isInteger(null)) // false,因为 null 不是整数

Number.isInteger() 方法在需要确保操作的是整数值而非浮点数或非数字类型的值时非常有用,常用于数据验证和处理。