Array.prototype.at()

方法接收一个整数值并返回该索引对应的元素,允许正数和负数。负整数从数组中的最后一个元素开始倒数

语法

1
ary.at(index)

参数

index:要返回的数组元素的索引。传递负数时,返回的元素将从数组的末端开始倒数

返回值

参数索引对应的值。如果找不到指定的索引,则返回 undefined

描述

在传递非负数时,at()方法等价于中括号表示法,例如ary[0]ary.at(0)均返回第一个元素;当索引小于0时,该方法将访问索引index + ary.length

at()方法是通用的,仅需要this具有length属性和以整数为键的属性

示例

获取数组中倒数第二个元素的不同方法。虽然示例中所有的方法都是可行的,但是at()方法更加简洁和可读

1
2
3
4
5
6
7
8
9
10
const colors = ['red', 'green', 'blue']

// 使用 length 获取
colors[colors.length-2] // 'green'

// 使用 slice() 方法获取
colors.slice(-2, -1)[0] // 'green'

// 使用 at() 方法
colors.at(-2) // 'green'

在类数组对象上调用at()

1
2
3
4
5
6
const aryLike = {
length: 2,
0: 'a',
1: 'b'
}
Array.prototype.at.call(aryLike, -1) // 'b'

Array.prototype.concat()

用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新的数组

语法

1
ary.concat(value0, value1, ..., valueN)

参数

valueN:数组或者值,将被合并到一个新的数组中。如果不传参数,则concat会返回调用此方法的现存数组的一个浅拷贝

返回值

新的 Array 实例

描述

concat方法创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(参数不是数组)。它不会递归到嵌套数组参数中

concat方法不会改变 this 或任何作为参数提供的数组,而是返回一个浅拷贝

示例

合并两个数组

1
2
3
4
const ary1 = ['a', 'b', 'c']
const ary2 = [1, 2, 3]
const ary = ary1.concat(ary2)
console.log(ary) // ['a', 'b', 'c', 1, 2, 3]

合并三个数组

1
2
3
4
5
const num1 = [1, 2, 3]
const num2 = [4, 5, 6]
const num3 = [7, 8, 9]
const numbers = num1.concat(num2, num3)
console.log(numbers) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

将值连接到数组

1
2
3
const ary1 = ['a', 'b', 'c']
const ary = ary1.concat(1, [2, 3])
console.log(ary) // ['a', 'b', 'c', 1, 2, 3]

合并到嵌套数组

1
2
3
4
5
6
7
8
9
const num1 = [[1]]
const num2 = [2, [3]]
const numbers = num1.concat(num2)
console.log(numbers) // [[1], 2, [3]]

// 修改 num1 的第一个元素
num1[0].push(4)

console.log(numbers) // [[1, 4], 2, [3]]

合并类数组对象
Symbol.isConcatSpreadable被设置为真值(例如:true)时,concat 会将类数组对象视为数组

1
2
3
const obj1 = { 0: 1, 1: 2, 2: 3, length: 3 }
const obj2 = { 0: 1, 1: 2, 2: 3, length: 3, [Symbol.isConcatSpreadable]: true }
console.log([0].concat(obj1, obj2)) // [ 0, { '0': 1, '1': 2, '2': 3, length: 3 }, 1, 2, 3 ]

Array.prototype.copyWithin()

方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度

语法

1
2
3
copyWithin(target)
copyWithin(target, start)
copyWithin(target, start, end)

参数

三个参数都为数组的索引

target:
  复制序列到该位置。如果是负数,target将从末尾开始计算。如果target大于等于数组长度,将不会发生拷贝。如果targetstart之后,复制的序列将被修改以符合数组长度

start
  开始复制元素的起始位置。如果是负数,start将从末尾开始计算。如果start被忽略,方法将会从 0 开始复制

end
  复制元素的结束位置(不包括这个位置的元素)。如果是负数,end将从末尾开始计算。如果被忽略,将一直复制到数组结尾

返回值

改变后的数组。会改变原数据,但不会改变原数组的长度

描述

三个参数都必须为整数

copyWithin方法不要求其 this 值必须是一个数组对象;除此之外,copyWithin是一个可变方法,它可以改变 this 对象本身,并返回它,而不仅仅是它的拷贝

copyWithin会保留空槽

copyWithin是一个可变方法,它不会改变 this 的长度 length,但是会改变 this 本身的内容,且需要时会创建新的属性

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const ary = [1, 2, 3, 4, 5]
const copyAry = ary.copyWithin(2) // [1, 2, 1, 2, 3]
console.log(ary) // [1, 2, 1, 2, 3]
copyAry === ary // true

[1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(-2, -3, -1) // [1, 2, 3, 3, 4]

[].copyWithin.call({length: 5, 3: 1}, 0, 3) // {0: 1, 3: 1, length: 5}

[1,2,,4].copyWithin(1,2,3) // [1,,,4]

Array.prototype.entries()

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

语法

1
entries()

返回值

一个新的 Array 迭代器对象

描述

当在稀疏数组上使用时,entries()方法迭代空槽,就像他们的值为undefined一样

entries()方法是通用的。它只要求this值具有length属性和以证书为键的属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 迭代索引和元素
const a = ['a', 'b', 'c'];

for(const [index, element] of a.entries()) {
console.log(index, element)
}
// 0 'a'
// 1 'b'
// 2 'c'

// 使用 for...of 循环
const array = ['a', 'b', 'c']
const arrayEntries = array.entries()

for(const element of arrayEntries){
console.log(element)
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

// 迭代稀疏数组
// entries() 将访问空槽,就像它们是 undefined 一样
for(const element of [, 'a'].entries()) {
console.log(element)
}
// [0, undefined]
// [1, 'a']

// 在非数组对象上调用 entries()
// entries() 方法读取 this 的 length 属性,然后访问每个整数索引
const arrayLike = {
length: 3,
0: 'a',
1: 'b',
2: 'c'
}
for(const entry of Array.prototype.entries.call(arrayLike)){
console.log(entry)
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

Array.prototype.every()

every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试,它返回一个布尔值。若是一个空数组,此方法在任何情况下都会返回 true

语法

1
2
3
4
5
6
every(element => { } )
every((element, index) => { } )
every((element, index, array) => { } )

every(callbackFn)
every(callbackFn, thisAry)

参数

  • callback 用来测试每个元素的函数,它可以接收三个参数:
    • element 用于测试的当前值
    • index 用于测试的当前值的索引
    • array 调用 every 的当前数组
  • thisAry(可选) 执行 callback 时使用的 this

返回值

如果回调函数的每一次返回都为 truthy 值,返回 true,否则返回 false

描述

every 方法为数组中的每一个元素执行一次 callback 函数,如果 callback 返回 falsy 值,every 方法会立即返回 false。否则,callback为每一个元素返回 trueevery 就会返回 truecallback 只会为那些已经被赋值的索引调用,不会为那些被删除或从未被赋值的索引调用

1
2
3
4
5
6
7
8
9
10
11
12
13
const ary = [0, 1, , undefined, null, 5, 6]
function fn(item, index) {
console.log(item, index);
return true
}
array.every(fn)

// 0 0
// 1 1
// undefined 3
// null 4
// 5 5
// 6 6

every 不会改变原数组

every 遍历的元素范围在第一次调用 callback 之前就已经确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。如果数组中存在的元素被更改,则它们传入 callback 的值是 every 访问到它们那一刻的值

Array.prototype.fill()

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引

语法

1
2
3
fill(value)
fill(value, start)
fill(value, start, end)

参数

  • value 用来填充数组元素的值
  • start 可选。起始索引,默认值为 0
  • end 可选。终止索引,默认值为 arr.length

返回值

修改后的数组

描述

如果 start 是个负数,则开始索引会被自动计算成为 length + start,其中 lengththis 对象的 length 属性。如果 end 是负数,则结束索引会被自动计算成为 length + end

fill 方法故意被设计成通用方法,该方法不要求 this 是数组

fill 方法是个可变方法,他会改变调用它的 this 对象本身,然后返回它,而不是返回一个副本

当一个对象被传递给 fill 方法的时候,填充数组的是这个对象的引用

示例

1
2
3
4
5
6
7
8
9
10
11
12
[1, 2, 3].fill(4) // [4, 4, 4]
[1, 2, 3].fill(4, 1) // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2) // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1) // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2) // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN) // [1, 2, 3]
Array(3).fill(4) // [4, 4, 4]
[].fill.call({ length: 3 }, 4) // { 0: 4, 1: 4, 2: 4, length: 3 }

// 当一个对象被传递给 `fill` 方法的时候,填充数组的是这个对象的引用
const arr = Array(3).fill({}) // [{}, {}, {}]
arr[0].hi = 'hi' // [{ hi: 'hi' }, { hi: 'hi' }, { hi: 'hi' }]

Array.prototype.filter()

filter() 方法创建给定数组一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素

语法

1
2
3
4
5
6
7
8
// 箭头函数
filter(element => { })
filter((element, index) => { })
filter((element, index, array) => { })

// 回调函数
filter(callbackFn)
filter(callbackFn, thisArg)

参数

  • callbackFn 用来测试数组中每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。它接受以下三个参数:
    • element 数组中当前正在处理的元素
    • index 正在处理的元素在数组中的索引
    • array 调用 filter() 的数组本身
  • thisArg 可选。执行 callbackFn 时,用于 this 的值

返回值

一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组

描述

filter() 为数组中的每个元素调用一次 callbackFn 函数,并利用所有使 callbackFn 返回 true 或等价于 true 的值的元素创建一个新数组

callbackFn 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callbackFn 测试的元素会被跳过,不会被包含在新数组中

如果 filter() 提供一个 thisArg 参数,则它会被作为 callbackFn 被调用时的 this 值。否则,callbackFnthis 值在非严格模式下将是全局对象,严格模式下为 undefinedcallbackFn 函数最终观察到的 this 值是根据通常函数所看到的 this 的规则确定的

filter() 不会改变原数组

filter() 遍历的元素范围在第一次调用 callbackFn 之前就已经确定了。修改已经访问过的或在确定的范围之外创建的元素,将不会被 callbackFn 访问。如果以相同的方式删除数组中的现有元素,则不会访问他们

Array.prototype.find()

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined

语法

1
2
3
4
5
6
7
8
// 箭头函数
find(element => { })
find((element, index) => { })
find((element, index ,array) => {})

// 回调函数
find(callbackFn)
find(callbackFn, thisArg)

参数

  • callbackFn 在数组每一项上执行的函数,接受 3 个参数:
    • element 当前遍历道的元素
    • index 当前遍历到的索引
    • array 数组本身
  • thisArg 可选 执行回调时用作 this 的对象

返回值

数组中第一个满足所提供测试函数的元素的值,否则返回 undefined

描述

find 方法对数组中的每一项元素执行一次 callbackFn 函数,直到有一个 callbackFn 返回 true。当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回 undefined

**callbackFn 函数会为数组中的每个索引调用,而不仅仅是那些被赋值的索引,这意味着对于稀疏数组来说,该方法的效率要低于那些只遍历有值的索引的方法

如果提供了 thisArg 函数,那么它将作为每次 callbackFn 函数执行时的 this,如果未提供,则使用 undefined

在第一次调用 callbackFn 函数时会确定元素的索引范围,因此在 find 方法开始执行之后添加到数组的新元素将不会被 callbackFn 函数访问到。如果数组中一个尚未被 callbackFn 函数访问到的元素的值被 callbackFn 函数所改变,那么当 callbackFn 函数访问到它时,它的值时根据它在数组中的索引所访问到的当时值。被删除的元素仍旧会被访问到,但是其值已经是 undefined 了

Array.prototype.findIndex()

findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1

语法

1
2
3
4
5
6
7
8
// 箭头函数
findIndex(element => { })
findIndex((element, index) => { })
findIndex((element, index, array) => { })

// 回调函数
findIndex(callbackFn)
findIndex(callbackFn, thisArg)

参数

  • callback 针对数组中的每个元素,都会执行该回调函数,执行时会自动传入下面三个参数:
    • element 当前元素
    • index 当前元素的索引
    • array 调用 findIndex 的数组
  • thisArg 可选。执行 callback 时作为 this 对象的值

返回值

数组中通过提供测试函数的第一个元素的索引。否则,返回 -1

描述

findIndex 方法对数组中的每个数组索引 0...length-1(包括)执行一次 callback 函数,直到找到一个 callback 函数返回真实值(强制为 true)的值。如果找到这样的元素,findIndex 会立即返回该元素的索引,如果回调从不返回真值,或者数组的 length 为 0,则 findIndex 返回 -1。在稀疏数组中,即使对于数组中不存在的条目的索引页会调用回调函数

findIndex 不会修改所调用的数组

在第一次调用 callback 函数时会确定元素的索引范围,因此在 findIndex 方法开始执行之后添加到数组的新元素将不会被 callback 函数访问到。如果数组中一个尚未被 callback 函数访问到的元素的值被 callback 函数所改变,那么当 callback 函数访问到它时,它的值将是根据它在数组中的索引所访问到的当前值。被删除的元素仍然会被访问到

Array.prototype.findLast()

findLast() 方法返回数组中满足提供的测试函数条件的最后一个元素的值。如果没有找到对应元素,则返回 undefined

语法

1
2
3
4
5
6
7
8
// 箭头函数
findLast(element => {})
findLast((element, index) => {})
findLast((element, index, array) => {})

// 回调函数
findLast(callbackFn)
findLast(callbackFn, thisArg)

参数

  • callbackFn 数组中测试元素的函数。函数在被调用时会传递以下参数
    • element 当前遍历到的元素
    • index 当前遍历到的元素的索引
    • array 调用 findLast() 的数组本身
  • thisArg 执行 callbackFn 时,用作 this 的对象

返回值

数组中满足提供的测试函数索引最高的元素;如果没有元素匹配,返回 undefined

描述

findLast() 方法对数组每一个元素按降序(索引从大到小)执行 callbackFn 函数,直到 callbackFn 返回一个真值。然后 callbackFn 返回该元素的值并停止遍历数组。如果 callbackFn 没有返回一个真值,则 findLast() 返回 undefined

callbackFn 会为数组中的每个元素调用,而不仅仅是那些被赋值的元素,这意味着对于稀疏数组来说,该方法的效率要低于那些只遍历有值的索引的方法

findLast() 方法不会改变调用它的数组,但是提供的 callbackFn 可以

findLast() 处理的元素是在第一次调用 callbackFn 之前设置的,因此:

  • callbackFn 不会访问在调用 findLast() 开始后才添加到数组中的任何元素
  • 给已访问过的索引重新赋值将不会被 callbackFn 重新访问
  • 给初始的范围外的索引赋值,其将不会被 callbackFn 访问
  • 如果 callbackFn 更改了数组中现有的、尚未访问的元素,则其传递给 callbackFn 的值将是 findLast() 访问该元素索引时的值
  • 仍然会访问已删除的元素

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 查找符合条件的数组中的最后一项
const ary = [
{name: 'apple', quantity: 2},
{name: 'banana', quantity: 0},
{name: 'fish', quantity: 1},
{name: 'cherry', quantity: 5}
]

function fn(item) {
return item.quantity < 2
}

console.log(ary.findLast(fn)) // {name: 'fish', quantity: 1}

// 用箭头函数和解构
console.log(ary.findLast(({ quantity }) => quantity < 2)) // {name: 'fish', quantity: 1}

Array.prototype.findLastIndex()

findLastIndex() 方法返回数组中满足提供的测试函数条件的最后一个元素的索引。若没有找到对应元素,则返回 -1

语法

1
2
3
4
5
6
7
8
// 箭头函数
findLastIndex(element => {})
findLastIndex((element, index) => {})
findLastIndex((element, index, array) => {})

// 回调函数
findLastIndex(callbackFn)
findLastIndex(callbackFn, thisArg)

参数

  • callbackFn 数组中测试元素的函数。函数在被调用时会传递以下参数:
    • element 当前遍历到的元素
    • index 当前遍历到的元素的索引
    • array 调用 findLastIndex() 的数组本身
  • thisArg 可选。执行 callbackFn 时,用作 this 的对象

返回值

数组中通过测试的最后一个元素(最大的索引)。如果没有任何元素匹配,则返回 -1

描述

findLastIndex() 方法对数组每一个元素降序(索引从大到小)执行 callbackFn 函数,直到 callbackFn 返回一个真值。然后 findLastIndex() 返回元素的索引并且停止迭代数组。如果 callbackFn 没有返回一个真值,则 findLastIndex() 返回 -1

callbackFn 会为数组中的每个元素调用,而不仅仅是那些被赋值的元素,这意味着对于稀疏数组来说,该方法的效率要低于那些只遍历有值的索引的方法

findLastIndex() 方法不会改变调用它的数组,但是提供的 callbackFn 可以。
findLastIndex() 处理的元素是在第一次调用 callbackFn 之前设置的,因此:

  • callbackFn 不会访问在调用 findLastIndex 开始后才添加到数组中的任何元素
  • 给已访问过的索引重新赋值将不会被 callbackFn 重新访问
  • 给初始的范围外的索引赋值,其将不会被 callbackFn 访问
  • 如果 callbackFn 更改了数组中现有的、尚未访问的元素,则其传递给 callbackFn 的值将是 findLastIndex() 访问该元素索引时的值
  • 仍然会访问已删除的元素

Array.prototype.flat()

flat() 方法会按一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回

语法

1
2
flat()
flat(depth)

参数

depth 可选。指定要提取嵌套数组的解构深度,默认值为 1

返回值

一个包含数组与子数组中所有元素的新数组。不会改变原数组

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 扁平化嵌套数组
const arr1 = [1,2,[3,4]]
arr1.flat() // [1,2,3,4]

const arr2 = [1,2[3,4,[5,6]]]
arr2.flat() // [1,2,3,4,[5,6]]

const arr2 = [1,2[3,4,[5,6]]]
arr2.flat(2) // [1,2,3,4,5,6]

// 使用 Infinity 可以展开任意深度的嵌套数组
const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// flat 方法会移除数组中的空项
const arr5 = [1,2,3,,4,5]
arr5.flat() // [1,2,3,4,5]

Array.prototype.flatMap()

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为 1 的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些

语法

1
2
3
4
5
6
7
8
// 箭头函数
flatMap((currentValue) => { })
flatMap((currentValue, index) => { })
flatMap((currentValue, index, array) => { })

// 回调函数
flatMap(callbackFn)
flatMap(callbackFn, thisArg)

参数

  • callback 可以生成一个新数组中的元素的函数,可以传入三个参数:
    • currentValue 当前正在数组中处理的元素
    • index 可选。数组中正在处理的当前元素的索引
    • array 可选。被调用的 map 数组
  • thisArg 可选。执行callback函数时使用的this

返回值

一个新的数组,其中每一个元素都是回调函数的结果,并且结构深度depth值为1。不会改变原数组

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// map() 与 flatMap()
const arr1 = [1, 2, 3, 4]

arr1.map(x => [x*2])
// [[2], [4], [6], [8]]

arr1.flatMap(x => [x*2])
// [2, 4, 6, 8]

// 如果有多层
arr1.flatMap(x => [[x*2]])
// [[2], [4], [6], [8]]

// 将包含几句话的数组拆分成单个词组成的新数组
let arr2 = ["it's Sunny in", "", "California"];

arr2.map(x => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]

arr2.flatMap(x => x.split(" "));
// ["it's","Sunny","in", "", "California"]

flatMap能用于在 map 期间增删项目。它的作用类似于 filter 的对立面。只需返回一个1项元素数组以保留该项,返回一个多元素数组以添加项,或返回一个0项元素数组以删除该项

1
2
3
4
5
// 移除所有负数并将奇数拆分成偶数和1
let a = [5, 4, -3, 20, 17, -33, -4, 18]

a.flatMap((n) => (n < 0) ? [] : (n % 2 == 0) ? [n] : [n-1, 1])
// [4, 1, 4, 20, 16, 1, 18]

Array.prototype.forEach()

forEach方法对数组的每个元素执行一次给定的函数

语法

1
2
3
4
5
6
7
8
// 箭头函数
forEach((element) => { })
forEach((element, index) => { })
forEach((element, index, array) => { })

// 回调函数
forEach(callbackFn)
forEach(callbackFn, thisArg)

参数

  • callbackFn 为数组中每个元素执行的函数。函数调用时带有以下参数
    • element 数组中正在处理的当前元素
    • index 数组中正在处理的当前元素的索引
    • array forEach() 方法正在操作的数组
  • thisArg 可选参数。当执行回调函数callbackFn时,用作this的值

返回值

undefined

描述

forEach()方法按升序为数组中含有效值的每一项执行一次callbackFn函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const arraySparse = [1, 3, /* empty */, 7];
let numCallbackRuns = 0;

arraySparse.forEach((element) => {
console.log({ element });
numCallbackRuns++;
});

console.log({ numCallbackRuns });

// { element: 1 }
// { element: 3 }
// { element: 7 }
// { numCallbackRuns: 3 }

如果thisArg参数有值,则每次callbackFn函数被调用时,this都会指向thisArg参数。如果省略了thisArg参数,或者其值为nullundefinedthis指向全局对象。如果使用箭头函数表达式来传入函数参数,thisArg 参数会被忽略,因为箭头函数在词法上绑定了 this 值

forEach()遍历的范围在第一次调用callbackFn前就会确定。调用forEach后添加到数组中的项不会被callbackFn访问到。如果已经存在的值被改变,则传递给callbackFn的值是forEach()遍历到他们的那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了,之后的元素将跳过(因为元素被删除后后面的元素的索引往前移了一位)

1
2
3
4
5
6
7
8
9
const words = ['one', 'two', 'three', 'four'];
words.forEach((word) => {
console.log(word);
if (word === 'two') {
words.shift(); //'one' 将从数组中删除
}
}); // one // two // four

console.log(words); // ['two', 'three', 'four']

forEach()map()reduce()不同的是,它总是返回 undefined 值,并且不可链式调用

forEach()被调用时,不会直接改变原数据,但是该数据可能会被callbackFn函数改变

除了抛出异常外,没有办法终止或跳出forEach()循环。如果需要提前终止循环,可以使用:

  • for 循环
  • for…of / for…in 循环
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()

forEach()方法要求使用同步函数—它不会等待promise执行完成

1
2
3
4
5
6
7
8
9
const ratings = [5, 4, 5];
let sum = 0;

const sumFunction = async (a, b) => a + b;
ratings.forEach(async (rating) => {
sum = await sumFunction(sum, rating);
});

console.log(sum) // 实际的输出:0

Array.from()

Array.from()方法对一个类似数组或可迭代对象创建一个新的、浅拷贝的数组实例

语法

1
2
3
4
5
Array.from(arrayLike, (element) => {})
Array.from(arrayLike, (element, index) => {})

Array.from(arrayLike, mapFn)
Array.from(arrayLike, mapFn, thisArg)

参数

  • arrayLike 想要转换成数组的伪数组对象或可迭代对象
  • mapFn 可选。如果指定了该参数,新数组中的每个元素会执行该回调函数
  • thisArg 可选。执行回调函数mapFn时的this对象

返回值

一个新的数组实例

描述

Array.from()可以通过以下方式来创建数组对象:

  • 伪数组对象(拥有一个length属性和若干索引属性的任意对象)
  • 可迭代对象(可以获取对象中的元素,如 Map 和 Set 等)

Array.from()方法有一个可选参数mapFn,可以让开发者在最后生成的数组上再执行一次map方法后再返回。也就是说Array.from(obj, mapFn, thisAry)就相当于Array.from(obj).map(mapFn, thisAry),除非创建的不是可用的中间数组

from()length属性为1,即Array.from.length === 1

在 ES6 中,Class语法允许我们为内置类型(比如Array)和自定义类新建子类(比如叫subArray)。这些子类也会继承父类的静态方法,比如subArray.from(),调用该方法后会返回子类subArray的一个实例,而不是Array的实例

示例

String生成数组

1
2
Array.from('foo')
// ['f', 'o', 'o']

Set生成数组

1
2
3
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]

Map生成数组

1
2
3
4
5
6
7
8
9
10
const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]

const mapper = new Map([['1', 'a'], ['2', 'b']]);
Array.from(mapper.values());
// ['a', 'b'];

Array.from(mapper.keys());
// ['1', '2'];

从类数组对象(arguments)生成数组

1
2
3
4
5
6
7
function f() {
return Array.from(arguments);
}

f(1, 2, 3);

// [ 1, 2, 3 ]

如果参数是一个普通对象

1
2
3
const obj = { a: 1, b: 2, c: 3}
Array.from(obj)
// []

使用箭头函数

1
2
3
4
5
Array.from([1, 2, 3], x => x + x);
// [2, 4, 6]

Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]

Array.prototype.includes()

includes() 方法用来判断一个数组是否包含一个指定的值,如果包含则返回true,否则返回false

语法

1
2
includes(searchElement)
includes(searchElement, fromIndex)

参数

  • searchElement 需要查找的元素值(比较字符串时是区分大小写的)
  • fromIndexfromIndex索引处开始查找searchElement。如果为负值,则按升序从array.length + fromIndex的索引开始搜,默认为 0

返回值

返回一个布尔值,如果在数组中(或fromIndex指定的范围中)找到了searchElement,则返回true,否则返回false

0 的值将全部视为相等,与符号无关(即 -0 与 0 和 +0 相等),但false不被认为与 0 相等

示例

1
2
3
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(2, 2) // false
[1, 2, 3, NaN].includes(NaN) // true

如果fromIndex大于等于数组长度,则将直接返回false,且不搜索该数组

1
2
3
const arr = ['a', 'b', 'c'];
arr.includes('c', 3); // false
arr.includes('c', 100); // false

如果fromIndex为负值,计算出的索引将作为开始搜索searchElement的位置。如果计算出的索引小于 0,则整个数组都会被搜索

1
2
3
4
5
6
const arr = ['a', 'b', 'c'];

arr.includes('a', -100); // true
arr.includes('b', -100); // true
arr.includes('c', -100); // true
arr.includes('a', -2); // false

inclides()方法有意设计为通用方法。它不要求this值是数组对象,所以它可以被用于其他类型的对象(比如类数组对象)

1
2
3
4
(function() {
console.log([].includes.call(arguments, 'a')); // true
console.log([].includes.call(arguments, 'd')); // false
})('a','b','c');

Array.prototype.indexOf()

indexOf()方法返回在数组中可以找到给定元素的第一个索引,如果不存在,则返回 -1

语法

1
2
indexOf(searchElement)
indexOf(searchElement, fromIndex)

参数

  • searchElement 要查找的元素
  • fromIndex 可选。开始查找的位置

返回值

首个被找到的元素在数组中的索引位置,若没有找到则返回 -1

描述

indexOf使用全等运算(===)判断searchElement与数组中包含的元素之间的关系

示例

1
2
3
const ary = [2, 8, 9]
ary.indexOf(2) // 0
ary.indexOf(7) // -1

Array.isArray()

Array.isArray()用于确定传递的值是否是一个Array

语法

1
Array.isArray(value)

参数

value 需要检测的值

返回值

如果值是 Array,则为true,否则为false

示例

1
2
// 鲜为人知的事实,Array.prototype 也是一个数组
Array.isArray(Array.prototype) // true

当检测Array实例时,Array.isArray优于instanceof,因为Array.isArray能检测iframe

1
2
3
4
5
6
7
8
9
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
const arr = new xArray(1,2,3); // [1,2,3]

// 正确检查 Array
Array.isArray(arr); // true
// Considered harmful, because doesn't work through iframes(被认为是有害的,因为不适用于iframe)
arr instanceof Array; // false

Array.prototype.join()

join()方法将一个数据(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串,用逗号或指定的分隔符字符串分隔。如果数组只有一个元素,那么将返回该元素而不使用分隔符

语法

1
2
join()
join(separator)

参数

separator 可选。指定一个字符串来分隔数组的每个元素。如果需要,将分隔符转换为字符串。如果省略,数组元素用逗号分隔。如果分隔符是空字符串,则所有元素之间都没有任何字符

返回值

一个所有数组元素连接的字符串。如果arr.length为 0,则返回空字符串

描述

所有数组元素被转换成字符串并连接到一个字符串中。如果一个元素是undefinednull,它将被转换为空字符串,而不是字符串undefinednull

Array.prototype.toString()会在内部访问join方法,不带参数。覆盖数组实例的join也将覆盖它的toString行为

当在稀疏数组上使用时,join()方法迭代空槽,就像他们的值为undefined一样

示例

使用不同的方式连接数据

1
2
3
4
5
const a = ['Wind', 'Water', 'Fire'];
a.join(); // 'Wind,Water,Fire'
a.join(', '); // 'Wind, Water, Fire'
a.join(' + '); // 'Wind + Water + Fire'
a.join(''); // 'WindWaterFire'

在稀疏数组上使用join()

1
2
3
// join() 将空槽视为 undefined,并产生额外的分隔符
[1, , 3].join() // '1,,3'
[1, undefined, 3].join() // '1,,3'

在非数组对象上调用join()

1
2
3
4
5
6
7
8
9
10
const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
};
console.log(Array.prototype.join.call(arrayLike));
// 2,3,4
console.log(Array.prototype.join.call(arrayLike, "."));
// 2.3.4

Array.prototype.keys()

keys() 方法返回一个包含数组中每个索引键的Array Iterator对象

语法

1
keys()

返回值

一个新的Array迭代器对象

示例

索引迭代器会包含那些没有对应元素的索引

1
2
3
4
5
const arr = ["a", , "c"];
const sparseKeys = Object.keys(arr);
const denseKeys = [...arr.keys()];
console.log(sparseKeys); // ['0', '2']
console.log(denseKeys); // [0, 1, 2]

Array.prototype.lastIndexOf()

lastIndexOf()方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从fromIndex处开始

语法

1
2
lastIndexOf(searchElement)
lastIndexOf(searchElement, fromIndex)

参数

  • searchElement 被查找的元素
  • fromIndex 可选。从此位置开始逆向查找。默认为数组的长度减1(arr.length - 1),即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的便宜。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找

返回值

数组中该元素最后一次出现的索引,如未找到返回 -1

描述

lastIndexOf使用严格相等(===)比较searchElement和数组中的元素

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
var array = [2, 5, 9, 2];
var index = array.lastIndexOf(2);
// index is 3
index = array.lastIndexOf(7);
// index is -1
index = array.lastIndexOf(2, 3);
// index is 3
index = array.lastIndexOf(2, 2);
// index is 0
index = array.lastIndexOf(2, -2);
// index is 0
index = array.lastIndexOf(2, -1);
// index is 3

Array.prototype.map()

map()方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成

语法

1
2
map(callbackFn)
map(callbackFn, thisAry)

参数

callbackFn 为数组中的每个元素执行的函数。它的返回值作为一个元素被添加到新数组中。该函数被调用时将传入以下参数:

  • element 数组中当前正在处理的元素
  • index 正在处理的元素在数组中的索引
  • array 调用了map()的数组本身

thisArg 可选。执行callbackFn时用作this的值

返回值

一个新数组,每个元素都是回调函数的返回值

描述

map()方法时一个迭代方法。它为数组中的每个元素调用一次提供的callbackFn函数,并用结果构建一个新数组

callbackFn仅在已分配值得数组索引处被调用。它不会在稀疏数组中的空槽处被调用

map()方法是一个复制方法。它不会改变this。然而,作为callbackFn提供的函数可以更改数组。在第一次调用callbackFn之前,数组的长度已经被保存。因此:

  • 当开始调用map()时,callbackFn将不会访问超出数组初始长度的任何元素
  • 对已访问索引的更改不会导致再次在这些元素上调用callbackFn
  • 如果数组中一个现有的、尚未访问的元素被callbackFn更改,则它传递给callbackFn的值将是该元素被修改后的值。被删除的元素则不会被访问到

map()方法是通用的。它只期望this值具有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
const numbers = [1, 4, 9]
const roots = numbers.map(item => item * 2)
console.log(roots) // [2, 8, 18]
console.log(numbers) // [1, 4, 9]

const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
};
console.log(Array.prototype.map.call(arrayLike, (x) => x ** 2));
// [ 4, 9, 16 ]

Array.of()

Array.of()静态方法通过可变数量的参数创建一个新的Array实例,而不考虑参数的数量或类型

语法

1
2
3
Array.of()
Array.of(element)
Array.of(element1, element2, elementN)

参数

  • element 用于创建数据的元素。可以是一个或 N 个

返回值

新的Array实例

描述

Array.of()Array()构造函数之间的区别在于对单个参数的处理:Array.of(7)创建一个具有单个元素 7 的数组,而Array(7)创建一个 length 为 7 的空数组(7 个空槽,而不是 7 个 undefined

1
2
3
4
5
Array.of(7) // [7]
Array(7) // 由 7 个空槽组成的数据

Array.of(1,2,3) // [1,2,3]
Array(1,2,3) // [1,2,3]

示例

1
2
3
4
5
6
Array.of(1) // [1]
Array.of(undefined) // [undefined]
Array.of(1,2,3) // [1,2,3]

// 当 this 值不是构造函数时,返回一个普通的 Array 对象
Array.of.call({}, 1) // [1]

Array.prototype.pop()

pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法会改变数组的长度

语法

1
pop()

返回值

从数组中删除的元素(当数组为空时返回 undefined)

描述

pop()方法从一个数组中删除并返回最后一个元素给调用者

pop()是修改方法,其改变了this的长度和内容

pop()方法是通用的。它只期望this值具有length属性和整数键属性。虽然字符串也是类数组对象,但是由于其不能被修改,所以pop()方法并不能应用在字符串上

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在非数组对象上调用 pop()
// pop() 方法会读取 this 上的 length 属性。如果规范化的 length 属性为0,length 会被再次设置为 0(鉴于之前可能是负数或者 undefined)。否则,返回并删除位于 length-1 处的属性
const arrayLike = {
length: 3,
unrelated: 'foo',
2: 4
}
Array.prototype.pop.call(arrayLike) // 4
console.log(arrayLike) // { length: 2, unrelated: 'foo' }

const plainObj = {}
Array.prototype.pop.call(plainObj) // undefined
console.log(plainObj) // { length: 0 }

Array.prototype.push()

push()方法将指定的元素添加到数组的末尾,并返回新的数组长度

语法

1
2
push()
push(element0, element1, ..., elementN)

参数

  • element 添加到数组末尾的元素

返回值

调用方法的对象的新 length 属性

Array.prototype.reduce()

reduce()方法对数组中的每个元素按序执行一个提供的 reducer 函数

语法

1
2
reduce(callbackFn)
reduce(callbackFn, initialValue)

参数

  • callbackFn 为数组中每个元素执行的函数。其返回值将座位下一次调用callbackFn时的accumulator参数。对于最后一次调用,返回值将作为reduce()的返回值。该函数被调用时将传入以下参数:
    • accumulator 上一次调用callbackFn的结果。在第一次调用时,如果指定了initialValue则为指定的值,否则为array[0]的值
    • currentValue 当前元素的值。在第一次调用时,如果指定了initialValue,则为array[0]的值,否则为array[1]
    • currentIndex currentValue在数组中的索引位置。在第一次调用时,如果指定了initialValue则为0,否则为1
    • array 调用了reduce()的数组本身
  • initialValue 可选。第一次调用回调时初始化accumulator的值,如果指定了initialValue,则callbackFn从数组中的第一个值作为currentValue开始执行,如果没用指定,则accumulator初始化为数组中的第一个值,并且callbackFn从数组中的第二个值作为currentValue开始执行。在这种情况下,如果数组为空(没有第一个值可以作为accumulator返回),则会抛出错误

返回值

使用reducer回调函数遍历整个数组后的结果

异常

如果数组为空且未提供initialValue,则会抛出异常 TypeError

描述

callbackFn仅对已分配值得数组索引进行调用。不会对稀疏数组中的空槽进行调用

reduce()不接受thisArg参数。callbackFn调用时始终以undefined作为this的值,如果callbackFn未处于严格模式,则该值将被替换为globalThis

reduce()不会改变被调用的数组,但是作为callbackFn提供的函数可能会改变数据。
在第一次调用callbackFn之前,数组的长度会被保存,因此:

  • 当开始调用reduce()时,callbackFn将不会访问超出数组初始长度的任何元素
  • 对已访问索引的更改不会导致再次在这些元素上调用callbackFn
  • 如果数组中的一个现有的、尚未访问的元素被callbackFn更改,则它传递给callbackFn的值将是该元素被修改后的值,被删除的元素则不会被访问

如果数组只有一个元素(无论位置如何)且未提供initialValue,或者提供了initialValue但数组为空,则将返回该单个值,而不调用callbackFn

reduce()会跳过稀疏数组中缺失的元素,但不会跳过undefined

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 展开嵌套数据
const flattened = [
[0, 1],
[2, 3],
[4, 5]
].reduce(accumulator, currentValue) => accumulator.concat(currentValue, [])
// flattened 的值是 [0, 1, 2, 3, 4, 5]

// 统计对象中值的出现次数
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
const currCount = allNames[name] ?? 0;
return {
...allNames,
[name]: currCount + 1,
};
}, {});
// countedNames 的值是: { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

// 使用 reduce() 来替代 .filter().map()
const numbers = [-5, 6, 2, 0];
const doubledPositiveNumbers = numbers.reduce((accumulator, currentValue) => {
if (currentValue > 0) {
const doubled = currentValue * 2;
return [...accumulator, doubled];
}
return accumulator;
}, []);
console.log(doubledPositiveNumbers); // [12, 4]

Array.prototype.reduceRight()

该方法是从右到左的顺序遍历,其他同Array.prototype.reduce()

Array.prototype.reverse()

reverse()方法会倒转数组中元素的顺序,并返回该数组的引用地址

语法

1
reverse()

返回值

原始数组反转后的引用。该方法会改变原始数组,而不是复制

描述

reverse()方法会保留空槽

reverse()方法是通用的。它只期望this具有length属性和正数键属性。虽然字符串也是类似于数组的,但这个方法不适用于它们,因为字符串是不可变的

示例

1
2
3
4
5
6
7
8
9
10
11
// 对稀疏数组使用 reverse()
[1,,3].reverse() // [3, 空, 1]

// 对非数组对象调用 reverse()
const arrayLike = {
length: 3,
unrelated: 'foo',
2: 4
}
Array.prototype.reverse.call(arrayLike) // {'0': 4, length: 3, unrelated: 'foo'}
// 索引 2 被删除了,因为原本的数据中索引 0 不存在了

Array.prototype.shift()

shift()方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度

语法

1
shift()

返回值

从数组中删除的元素;如果数组为空则返回undefined

描述

shift方法移除索引为 0 的元素,并将后续元素的下标依次向前移动,然后返回被移除的元素。如果length属性的值为 0,则返回undefined

shift()方法是一个改变方法。它改变了this的长度和内容

shift()方法是通用的。它只期望this值具有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const myFish = ["angel", "clown", "manage", "surgeon"];
const shifted = myFish.shift();
console.log('调用 shift 之后:', myFish); // 调用 shift 之后: ['clown', 'manage', 'surgeon']
console.log('被删除的元素:' + shifted); // "被删除的元素:angel"

// 在 while 循环中使用 shift() 清空数据
const names = ["Andrew", "Tyrone", "Paul", "Maria", "Gayatri"];
while(typeof (i = names.shift()) !== 'undefined'){
console.log(i)
}
// Andrew, Tyrone, Paul, Maria, Gayatri

// 在非数组对象上调用 shift()
// shift() 方法会读取 this 的 length 属性。如果规范化长度为 0 或负值或 undefined,length 会再次设置为 0,否则,返回 0 处的属性,其余属性向左移动 1,length 属性递减 1
const arrayLike = {
length: 3,
unrelated: "foo",
2: 4,
};
Array.prototype.shift.call(arrayLike) // undefined 因为索引 0 处是一个空槽
console.log(arrayLike) { length: 2, unrelated: 'foo', 1: 4 }

const plainObj = {};
Array.prototype.shift.call(plainObj)
console.log(plainObj) // { length: 0 }

Array.prototype.slice()

slice()方法返回一个新的数组对象,这一对象是一个由startend决定的原数组的浅拷贝,其中startend代表了数组元素的索引。原始数组不会被改变

语法

1
2
3
slice()
slice(start)
slice(start, end)

参数

  • start 可选 提取的开始索引(默认为0),会转换为整数
    • 如果索引为负数,则从数组末尾开始计算(start + array.length
    • 如果 start + array.length < 0,或者没有提供 start,则使用 0
    • 如果start大于数据长度,则不提取任何元素
  • end 可选 提取终止处的索引,会转换为整数。slice()会提取到不包括end的位置
    • 如果索引为负数,则从数组末尾开始计算(end + array.length
    • 如果 end + array.length < 0,则使用 0
    • 如果 end >= array.length或者没有提供end,则使用array.length,提取所有元素直到末尾
    • 如果end在规范化后小于或等于start,则不提取任何元素

返回值

一个含有被提取元素的新数组

描述

slice()方法是一个复制方法,它不会改变this,而是返回一个浅拷贝

slice()方法会保留空槽,如果被切片的部分是稀疏的,则返回的数组也是稀疏的

slice()方法是通用的。它只要求this上有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 在类数组对象上调用 slice()
// slice() 方法会读取 this 对象的 length 属性,然后从 start 到 end 读取整数键属性,并将他们定义在一个新创建的数组中
const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
};
Array.prototype.slice.call(arrayLike, 1, 3) // [3, 4]

// 使用 slice() 把类数组转化为数组
const slice = Function.prototype.call.bind(Array.prototype.slice);
function list() {
return slice(arguments);
}
const list1 = list(1, 2, 3); // [1, 2, 3]

// 在稀疏数组上使用 slice()
console.log([1, 2, , 4, 5].slice(1, 4)) // [2, empty, 4]

Array.prototype.some()

some()方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true,则返回 true,否则返回 false。它不会修改数组

语法

1
2
some(callbackFn)
some(callbackFn, thisArg)

参数

  • callbackFn 为数组中的每个元素执行的函数。该函数被调用时将传入以下参数:
    • element 数组中当前正在处理的元素
    • index 正在处理的元素在数组中的索引
    • array 调用了some()的数组本身
  • thisArg 可选 执行callbackFn时用作this的值

返回值

如果回调函数对数组中至少一个元素返回真值,则返回 true,否则返回 false

描述

some()方法是一个迭代方法。它为数组中的每个元素调用一次指定的callbackFn函数,直到callbackFn返回一个真值。如果找到这样的元素,some()方法会立即返回true并停止遍历数组。否则,如果callbackFn对所有元素都返回假值,some()就会返回false

对于一个空数组,任何条件下都返回false

callbackFn仅针对已分配值的数组索引调用。它不会为稀疏数组中的空槽调用

some()不会改变调用它的数组,但指定的callbackFn函数可以。数组的长度是在第一次调用callbackFn之前保存的,因此:

  • 当开始调用some()时,callbackFn将不会访问超出数组初始长度的任何元素
  • 对已访问索引的更改不会导致再次在这些元素上调用callbackFn
  • 如果数组中一个现有的、尚未访问的元素被callbackFn更改,则它传递给callbackFn的值将是该元素被修改后的值。被删除的元素则不会被访问

some()方法是通用的。它只期望this值具有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// some() 不会在空槽上运行它的断言函数
console.log([1, , 3].some((x) => x === undefined)); // false
console.log([1, , 1].some((x) => x !== 1)); // false
console.log([1, undefined, 1].some((x) => x !== 1)); // true

// 在非数组对象上调用 some()
// some() 方法读取 this 的 length 属性,然后访问每个整数索引,直到到达末尾或 callbackFn 返回 true
const arrayLike = {
length: 3,
0: "a",
1: "b",
2: "c",
};
console.log(Array.prototype.some.call(arrayLike, (x) => typeof x === "number")); // false

Array.prototype.sort()

sort()方法就地对数组的元素进行排序,并返回对相同数组的引用。默认排序是将元素转换为字符串,然后按照它们的 UTF-16 码元值升序排序

语法

1
2
sort()
sort(compareFn)

参数

  • compareFn 可选。定义排序顺序的函数。返回值应该是一个数字。其正负性表示两个元素的相对顺序。该函数使用以下参数调用:
    • a 第一个用于比较的元素。不会是undefined
    • b 第二个用于比较的元素,不会是undefined

如果省略该函数,数组元素会被转换为字符串,然后根据每个字符的 Unicode 码位值进行排序

返回值

经过排序的原始数组的引用

描述

如果没有提供compareFn,所有非undefined的数组元素都会被转换为字符串,并按照 UTF-16 码元顺序比较字符串进行排序。例如:在数值排序中,9 出现在 80 之前,但因为数字会被转换为字符串,在 Unicode 顺序中 “80” 排在 “9” 之前。所有的undefined元素都会被排序到数组的末尾

sort()方法保留空槽。如果源数组是稀疏的,则空槽会被移动到数组的末尾,并始终排在所有undefined元素的后面

如果提供了compareFn,所有非undefined的数组元素都会按照比较函数的返回值进行排序(所有的undefined元素都会被排序到数组的末尾,并且不调用compareFn
| compareFn(a,b)返回值 | 排序顺序 |
| :——————–: | :——————–: |
| >0 | a放到b后 |
| <0 | ab前 |
| ===0 | 保持ab原来的顺序 |

sort()方法是通用的,它只期望this值具有length属性和整数键属性。虽然字符串也类似于数组,但此方法不适用于字符串,因为字符串是不可变的

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 对象数组的排序
// 对象数组可以通过比较它们的某个属性的值来排序
const items = [
{ name: "Edward", value: 21 },
{ name: "Sharpe", value: 37 },
{ name: "And", value: 45 },
{ name: "The", value: -12 },
{ name: "Magnetic", value: 13 },
{ name: "Zeros", value: 37 },
];
// 根据 value 排序
items.sort((a, b) => a.value - b.value);
// 根据 name 排序
items.sort((a, b) => {
const nameA = a.name.toUpperCase(); // 忽略大小写
const nameB = b.name.toUpperCase(); // 忽略大小写
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// name 必须相等
return 0;
})

// 对非 ASCII 字符排序
// 当排序非 ASCII 字符的字符串(如包含类似 e、é、è、a、ä 等字符的字符串)时,一些非英语语言的字符串需要使用`String.localeCompare`。这个函数可以将函数排序到正确的顺序
var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];
items.sort(function (a, b) {
return a.localeCompare(b);
});
// items 是 ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé']

// 在稀疏数组上使用sort(),空槽会被移动到数组的末尾
console.log(["a", "c", , "b"].sort()); // ['a', 'b', 'c', empty]
console.log([, undefined, "a", "b"].sort()); // ["a", "b", undefined, empty]

// 在类数组对象上调用 sort()
// sort() 方法会读取 this 的 length 属性,然后它会收集在 e 到 length-1 范围内所有已存在的整数键属性,对它们进行排序,然后写回。如果范围内存在缺失的属性,则相应的尾随属性将被删除,好像不存在的属性被排序到末尾一样
const arrayLike = {
length: 3,
unrelated: "foo",
0: 5,
2: 4,
};
console.log(Array.prototype.sort.call(arrayLike));
// { '0': 4, '1': 5, length: 3, unrelated: 'foo' }

Array.prototype.splice()

splice()方法通过移除或者替换已存在的元素和/或添加信元素就地改变一个数组的内容

语法

1
2
3
4
splice(start)
splice(start, deleteCount)
splice(start, deleteCount, item1)
splice(start, deleteCount, item1, item2, itemN)

参数

  • start 从0开始计算的索引,表示要开始改变数组的位置,它会被转换成整数
    • 负索引从数组末尾开始计算,如果start < 0,使用start + array.length
    • 如果start < -array.length,使用0
    • 如果start >= array.length,则不会删除任何元素,但是该方法会表现为添加元素的函数,添加所提供的哪些元素
    • 如果start被省略了(即调用splice()时不传递参数),则不会删除任何元素。这与传递undefined不同,后者会被转换为 0
  • deleteCount 可选。一个整数,表示数组中要从start开始删除的元素数量
    • 如果不传,从start删到数组末尾
    • 如果大于或等于从start到数组末尾的长度,从start删到数组末尾
    • 如果想要删除start后的所有元素并插入值,可以传Infinity,如果不传的话,显示的undefined会转换为 0
    • 如果传 0 或者负数,则不会移除任何元素
  • item1,...,itemN 可选 从start开始要加入到数组中的元素,如果不指定,splice()将只从数组中删除元素

返回值

一个包含了删除的元素的数组
如果只移除一个元素,则返回一个元素的数组
如果没有删除任何元素,则返回一个空数组

描述

splice()方法是一个修改方法,它可能会改变this的内容,如果要插入的元素数量与要删除的元素数量不同,数组的length也会改变

如果删除的部分是稀疏的,则splice()返回的数组也是稀疏的,对应的索引为空槽

splice()方法是通用的,它只期望this值具有length属性和整数键属性(不包括字符串)

示例

1
2
3
4
5
6
7
8
9
// splice() 方法读取 this 的 length 属性,然后根据需要更新整数键属性和 length 属性
const arrayLike = {
length: 3,
unrelated: 'foo',
0: 5,
2: 4
}
console.log(Array.prototype.splice.call(arrayLike, 0, 1, 2, 3)) // [ 5 ]
console.log(arrayLike) // { '0': 2, '1': 3, '3': 4, length: 4, unrelated: 'foo' }

Array.prototype.toLocaleString()

toLocaleString()方法返回一个字符串,表示数组中的所有元素。每个元素通过调用它们自己的toLocaleString方法转换为字符串,并且使用特定于语言环境的字符串(例如逗号)分隔开

语法

1
2
3
toLocaleString()
toLocaleString(locales)
toLocaleString(locales, options)

参数

  • locales 可选。带有 BCP47 语言标签的字符串,或者此类字符串的数组
  • options 可选。一个具有配置属性的对象

返回值

一个字符串,表示数组中的所有元素

描述

Array.prototype.toLocaleString方法遍历数组内容,并使用提供的localesoptions参数调用每个元素的toLocaleString方法,通过由实现定义的分隔符将转换后的字符串拼接起来。方法本身并不使用这两个参数,而是将其传递给每个元素的toLocaleString()。分隔符的选择取决于主机当前的语言环境,而不是locales参数

如果一个元素是undefinednull,它会被转换为空字符串,而不是"null"或者"undefined"

当用于稀疏数组时,toLocaleString()方法迭代时会把空槽当作undefined一样处理它

toLocaleString()方法是通用的,它只期望this值具有length属性和整数键属性

示例

数组元素通过使用他们的toLocaleString方法转换为字符串

  • Object Object.prototype.toLocaleString()
  • Number Number.prototype.toLocaleString()
  • Date Date.prototype.toLocaleString()
1
2
3
4
// 显示货币符号
const prices = [7, 500, 8123]
prices.toLocaleString("ja-JP", { style: "currency", currency: "JPY" });
// "¥7,¥500,¥8,123,¥12"

toLocaleString()将空槽视为undefined,并生成一个额外的分隔符

1
[1, , 3].toLocaleString() // '1,,3

在非数组对象上,toLocaleString()方法读取thislength属性,然后访问每个整数索引

1
2
3
4
5
6
7
const arrayLike = {
length: 3,
0: 1,
1: 2,
2: 3
}
Array.prototype.toLocaleString.call(arrayLike) // 1,2,3

Array.prototype.toReversed()

Array实例的toReversed()方法是reverse()方法对应的复制版本。它返回一个元素顺序相反的新数组

reverse()的区别

  • 当用于稀疏数组时,toReversed()方法迭代空槽,就像他们的值是undefined一样
  • toReversed()不改变原始数组,而是返回一个新的数组

Array.prototype.toSorted()

Array实例的toSorted()方法是sort()方法的复制方法版本。它返回一个新数组,其元素按升序排列

sort()的区别

  • toSorted()迭代时会将空槽视为具有undefined值的元素
  • toSorted()不改变原始数组,而是返回一个新的数组

Array.prototype.toSpliced()

Array实例的toSpliced()方法是splice()方法的复制版本。它返回一个新数组,并在给定的索引处删除和/或替换了一些元素

splice()的区别

  • toSpliced()方法在新数组中空槽将会被替换成undefined
  • toSpliced()不改变原始数组,而是返回一个新数组。因此,该方法不会返回已删除的元素

Array.prototype.toString()

toString()方法返回一个字符串,表示指定的数组及其元素

语法

1
toString()

返回值

一个表示数组元素的字符串

描述

Array对象覆盖了ObjecttoString方法。数组的toString方法实际上在内部调用了join()方法来拼接数组并返回一个包含所有数组元素的字符串,元素之间用逗号分隔。如果join方法不可用或者不是函数,则会使用Object.prototype.toString来代替,并返回[object Array]

1
2
3
4
5
const ary = []
ary.join = 1 // 将 join 重新赋值为非函数的值
ary.toString() // [object Array]

Array.prototype.toString.call({ join: () => 1 }) // 1

当数组需要被表示为文本值,或者当数组在字符串拼接中被引用时,JavaScript 会自动调用toString方法

示例

1
2
3
4
5
6
7
8
9
// const ary1 = [1, 2, 'a', '1a']
ary1.toString() // "1,2,a,1a"

// 与 join() 的行为一致,toString() 将空槽视为 undefined 并生成一个额外的分隔符
[1, , 3].toString() // "1,,3"

// toString()是通用的,它期望 this 具有 join() 方法,如果不存在,则使用 Object.prototype.toString()
Array.prototype.toString.call({ join: () => undefined }) // undefined
Array.prototype.toString.call({ join: "not function" }) // "[object Object]"

Array.prototype.unshift()

unshift()方法将指定元素添加到数组的开头,并返回数组的新长度

语法

1
2
3
4
unshift()
unshift(element0)
unshift(element0, element1)
unshift(element0, element1, /*...*/ elementN)

参数

element 添加到arr开头的元素

返回值

返回调用方法对象的新length属性

描述

unshift()方法将给定的值插入到数组对象的开头

如果多个元素作为参数传递,它们将被插入到对象开头的块中,插入顺序与它们作为参数传递的顺序完全相同。因此,调用一次unshift()方法并传递n个参数,与调用n次并传递 1 个参数,不会产生相同的结果

1
2
3
4
5
6
7
8
9
let arr = [4, 5, 6]
arr.unshift(1, 2, 3)
console.log(arr) // [1, 2, 3, 4, 5, 6]

arr = [4, 5, 6]
arr.unshift(1)
arr.unshift(2)
arr.unshift(3)
console.log(arr) // [3, 2, 1, 4, 5, 6]

unshift()方法是通用的。它只期望this值具有length属性和整数键属性(该方法不适用于字符串)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const arr = [1, 2];
arr.unshift([-4, -3]); // 新的数组长度是 6
// 数组是 [[-4, -3], 1, 2]

arr.unshift([-7, -6], [-5]); // 新的数组长度是 8
// 数组是 [ [-7, -6], [-5], [-4, -3], 1, 2 ]

// 在非数组对象中使用 unshift(),unshift 方法会读取 this 的 length 属性,然后将 0 到 length-1 范围内的所有属性按参数数量右移,将 length 设置为之前的长度加上前置元素的数量
const arrayLike = {
length: 3,
unrelated: 'foo',
2: 4
}
Array.prototype.unshift.call(arrayLike, 1, 2)
console.log(arrayLike) // { 0: 1, 1: 2, 4: 4, length: 5, unrelated: 'foo' }

const plainObj = {}
Array.prototype.unshift.call(plainObj, 1, 2)
console.log(plainObj) // { 0: 1, 1: 2, length: 2 }

Array.prototype.values()

values()方法返回一个新的数组迭代器对象,该对象迭代数组中每个元素的值

语法

1
values()

返回值

一个新的可迭代迭代器对象

描述

Array.prototype.values()Array.prototype[@@iterator]()的默认实现

1
Array.prototype.values === Array.prototype[Symbol.iterator] // true

当应用于稀疏数组时,values()方法会将空槽作为undefined迭代

values()方法是通用的,它只需要this值具有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 由于 values() 返回一个可迭代迭代器对象,可以使用 for……of 循环来迭代它
const arr = ["a", "b", "c", "d", "e"];
const iterator = arr.values()
for (const letter of iterator){
console.log(letter)
}
// "a" "b" "c" "d" "e"

// `values()`返回的可迭代对象是不可重复使用的。当`next().done = true`或`currentIndex > length`时,`for……of`循环结束,进一步迭代它没有任何效果
for (const letter of iterator){
console.log(letter)
}
// undefined

// 由于返回值也是一个迭代器,可以直接调用 next() 方法
const arr = ["a", "b", "c", "d", "e"];
const iterator = arr.values();
iterator.next(); // { value: "a", done: false }
iterator.next(); // { value: "b", done: false }
iterator.next(); // { value: "c", done: false }
iterator.next(); // { value: "d", done: false }
iterator.next(); // { value: "e", done: false }
iterator.next(); // { value: undefined, done: true }
console.log(iterator.next().value); // undefined

// 如果使用 break 语句提前结束迭代,当继续迭代时,迭代器可以从当前位置恢复迭代
const arr = ["a", "b", "c", "d", "e"];
const values = arr.values();
for (const letter of values) {
console.log(letter);
if (letter === "b") {
break;
}
}
// "a" "b"

for (const letter of values) {
console.log(letter);
}
// "c" "d" "e"

// values() 返回的数组迭代器对象中没有存储任何值,但是它存储了用于创建它的数组的地址,并在每次迭代中读取当前访问的索引。因此,它的迭代输出取决于在迭代时存储在该索引中的值。如果数组中的值发生了改变,数组迭代器对象的值也会改变
const arr = ["a", "b", "c", "d", "e"];
const iterator = arr.values();
console.log(iterator); // Array Iterator { }
console.log(iterator.next().value); // "a"
arr[1] = "n";
console.log(iterator.next().value); // "n"

// 在类数组上调用 values(), values() 会读取 this 的 length 属性,然后访问每个整数索引
const arrayLike = {
length: 3,
0: "a",
1: "b",
2: "c",
};
for (const entry of Array.prototype.values.call(arrayLike)) {
console.log(entry);
}
// a
// b
// c

Array.prototype.with()

Array实例的with()方法是使用方括号表示法修改指定索引值的复制方法版本。它会返回一个新数组,其指定索引处的值会被新值替换

语法

1
array.with(index, value)

参数

  • index 要修改的数组索引,将会转换为整数
    • 负数索引规则:index + array.length
    • 如果规范化后的索引超出数组边界,会抛出 RangeError
  • value 要分配给指定索引的任何值

返回值

一个全新的数组,其中index索引处的元素被替换为value

异常

RangeError index > array.lengthindex < -array.length时抛出

描述

with()通过返回一个指定索引处的值被新值替换的新数组,来改变数组中指定索引处的值。原数组不会被改变

如果原数组是稀疏数组,新数组对应的空白索引位置会被替换为undefined

with()方法是通用的,它只期望this值具有length属性和整数键属性

示例

1
2
3
4
5
6
7
8
9
// with() 方法会读取 this 上的 length 属性,之后读取 this 上的每个整数键并写入到新数组中,同时 value 会被写入指定的 index
const arrayLike = {
length: 3,
unrelated: "foo",
0: 5,
2: 4,
};
console.log(Array.prototype.with.call(arrayLike, 0, 1));
// [ 1, undefined, 4 ]