Chipmunk & Panda

-- 鼠熊部落格

All work and no play makes Jack a dull boy.

JavaScript 数组常用操作

创建、检测、复制、填充、添加删除元素、排序、拼接、截取、插入、搜索、迭代、归并。

创建

构造函数方法

  • 空数组
    1
    2
    let arr = new Array()
    console.log(arr) // []
  • 指定长度的数组(后期可改)
    1
    2
    let arr = new Array(6)
    console.log(arr) // [ <6 empty items> ]
  • 含有内容的数组
    1
    2
    let arr = new Array('土土', '土士', '士土', '士士')
    console.log(arr) // [ '土土', '土士', '士土', '士士' ]

字面量方法

字面量方法没法指定数组长度。

1
2
let arr1 = [] // 空数组
let arr2 = ['土土', '土士', '士土', '士士'] // 非空数组

from()of()

from 将类数组结构转换为数组实例,也可对现有数组执行浅复制;of 将一组参数转换为数组实例,用于替代 Array.prototype.slice.call(arguments)

1
2
let arr1 = Array.from('魑魅魍魉') // [ '魑', '魅', '魍', '魉' ]
let arr2 = Array.of('魑', '魅', '魍', '魉') // [ '魑', '魅', '魍', '魉' ]

数组空位

可以通过留空来创建含空元素的数组,空元素会被处理为 undefined,但建议通过显示使用 undefined 来代替留空。

1
2
let arr1 = [1, , , , 5] // [ 1, <3 empty items>, 5 ]
let arr2 = [1, undefined, undefined, undefined, 5] // [ 1, undefined, undefined, undefined, 5 ]

注意,当最后一个元素为空时,最后一个逗号会被忽略。

1
2
3
console.log([1]) // [ 1 ]
console.log([1, , ,]) // [ 1, <2 empty items> ]
console.log([1, , , undefined]) // [ 1, <2 empty items>, undefined ]

检测

判断一个对象是否为数组。在只有一个全局执行上下文时,可以直接使用 instanceof

1
console.log([] instanceof Array) // true

但当存在多个全局执行上下文时,可能会有两个不同版本的 Array 构造函数,如果要把数组从一个框架传给另一个框架,则这个数组的构造函数将有别于在第二个框架内本地创建的数组。此时应使用 Array.isArray() 方法。

1
console.log(Array.isArray([])) // true

复制

copyWithin() 会按照指定范围浅复制数组中的部分内容,然后将它们插入到指定索引开始的位置。方法接受 3 个参数:

  • target(必需):插入目标索引位置。
  • start(可选):复制起点。
  • end(可选,默认为 array.length):复制终点。
1
2
3
4
5
6
7
8
let arr1 = [0, 1, 2, 3, 4, 5]
arr1.copyWithin(3) // [ 0, 1, 2, 0, 1, 2 ]

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

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

方法静默忽略超出数组边界、零长度及方向相反的索引范围,复制索引表示倒数。

填充

fill() 方法与 copyWithin 方法相似。

  • value(必需):填充值。
  • start(可选):填充起点。
  • end(可选,默认为 array.length):填充终点。
1
2
3
4
let arr = [6, 6, 6, 6]
arr.fill(1) // [ 1, 1, 1, 1 ]
arr.fill(2, 2) // [ 1, 1, 2, 2 ]
arr.fill(3, 0, 1) // [ 3, 1, 2, 2 ]

添加删除元素

能够向数组进行添加、删除元素的方法包括 push()pop()unshift()shift() 以及 splice()

push()pop() 在数组队尾进行添加和删除元素。

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

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

unshift()shift() 在数组队首进行添加和删除元素。

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

console.log(arr.shift()) // 3
console.log(arr) // [ 4, 5, 6 ]

拼接为字符串

使用 join() 将数组拼接为字符串后输出,方法接收参数作为拼接的分隔符,默认为“,”。

1
2
3
let arr = [1, 2, 3, 4]
console.log(arr.join()) // 1,2,3,4
console.log(arr.join('#')) // 1#2#3#4

splice()

splice() 方法对数组中指定位置的元素进行删除、插入、替换,方法接收参数如下:

  • index(必需):添加或删除元素的索引位置。
  • howmany(可选):删除元素数目,留空则删除从 index 到数组结尾的所有元素。
  • item1, …, itemX(可选):要插入的新元素。

删除元素

1
2
3
4
// 从 2 开始,删除 3 个元素
let arr = [0, 1, 2, 3, 4, 5, 6]
console.log(arr.splice(2, 3)) // [ 2, 3, 4 ]
console.log(arr) // [ 0, 1, 5, 6 ]

插入元素

只要将删除元素数设为 0,就可以单纯插入元素。

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

原插入位置的元素会被挪到新插入元素的后面,如上述代码中 2 就被移到了插入到 7、8、9 之后。

替换元素

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

排序

使用 reverse() 方法对数组进行单纯的反向排序。

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

使用 sort() 对数组按规则排序,方法接收一个比较函数,该函数接收两个参数,函数返回负值时表示参数一应排在参数二前面,返回正值时则参数一排在参数二后面,返回 0 则两参数相等。

当未传入比较函数时,方法会对将每项元素的字符串转换结果作为比较依据,结果按升序排列。

1
2
3
4
let arr = [9, 5, 2, 7, 10]
arr.sort() // [ 10, 2, 5, 7, 9 ]
arr.sort((a, b) => a - b) // [ 2, 5, 7, 9, 10 ]
arr.sort((a, b) => b - a) // [ 10, 9, 7, 5, 2 ]

拼接

使用 concat 方法将一个数组拼接到另一个数组之后,该方法不改变原数组。

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

截取

使用 slice() 方法从原数组截取一部分得到新数组,该方法不会改变原数组。

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

搜索

使用 indexOf()lastIndexOf()includes() 方法在数组中搜索指定内容,除 lastIndexOf() 从后往前搜索外,另外俩方法从前往后搜索。三个方法均接收要搜索的元素以及可选的起始搜索位置,除 includes() 返回布尔值,另外俩方法搜索成功则返回索引位置,否则返回 -1。

1
2
3
console.log(arr.indexOf(3, 6)) // -1
console.log(arr.lastIndexOf(3, 2)) // -1
console.log(arr.includes(9527)) // false

迭代

参考《JavaScript 高级程序设计》

ECMAScript 为数组定义了 5 个迭代方法。每个方法接收两个参数:以每一项为参数运行的函数,以及可选的作为函数运行上下文的作用域对象(影响函数中 this 的值)。传给每个方法的函数接收 3 个参数:数组元素、元素索引和数组本身。因具体方法而异,这个函数的执行结果可能会也可能不会影响方法的返回值。

every()

数组每一项的函数运行结果均为 true 时才返回 true

1
2
3
let arr = [0, 1, 2, 3, 4]
console.log(arr.every((value, insex, array) => value < 3)) // false
console.log(arr.every((value, insex, array) => value < 6)) // true

some()

数组只要有一项的函数运行结果为 true 就返回 true

1
2
3
let arr = [0, 1, 2, 3, 4]
console.log(arr.some((value, insex, array) => value < 3)) // true
console.log(arr.some((value, insex, array) => value < 0)) // false

filter()

返回函数运行结果为 true 的项。

1
2
let arr = [0, 1, 2, 3, 4]
console.log(arr.filter((value, index, array) => value % 2 === 0)) // [ 0, 2, 4 ]

forEach()

对每一项执行传入的函数,没有返回值。

1
2
3
4
5
6
7
8
9
let arr = [0, 1, 2, 3, 4]
arr.forEach((value, index, array) => {
console.log(`value: ${value}, index: ${index}`)
})
// value: 0, index: 0
// value: 1, index: 1
// value: 2, index: 2
// value: 3, index: 3
// value: 4, index: 4

map()

对每一项执行传入的函数,返回结果构成的数组。

1
2
let arr = [0, 1, 2, 3, 4]
console.log(arr.map((value, index, array) => 2 ** value)) // [ 1, 2, 4, 8, 16 ]

归并

reduce() 从前往后遍历归并,reduceRight() 从后往前遍历归并。

参考《Javascript 高级程序设计》

这两个方法都接收两个参数:对每一项都会运行的归并函数,以及可选的以之为归并起点的初始值。传给 reduce()reduceRight() 的函数接收 4 个参数:上一个归并值、当前项、当前项的索引和数组本身。这个函数返回的任何值都会作为下一次调用同一个函数的第一个参数。如果没有给这两个方法传入可选的第二个参数(作为归并起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let arr = [0, 1, 2, 3, 4]
console.log(
arr.reduce(
(previousValue, currentValue, currentIndex, array) =>
previousValue + currentValue
)
) // 10
console.log(
arr.reduce(
(previousValue, currentValue, currentIndex, array) =>
previousValue + currentValue,
''
)
) // 01234
console.log(
arr.reduceRight(
(previousValue, currentValue, currentIndex, array) =>
previousValue + currentValue,
''
)
) // 43210