【JS】数组详解
js数组详解以及分类
前言
数组是js中最常用到的数据集合,它是引用数据类型的一种(其他二者为Object和Function),但其本质是Object。
一、数组的组成
数组由三部分组成,分别是
索引
、元素
和length
。
索引:用于标识元素,默认从0开始依次递增,也叫下标。
元素:存储数据的值,可以为任意数据类型,如果元素也为数组,就称为多维数组,嵌套了几层数组就是几维数组。
length:数组的长度(元素个数,即最大索引+1),当Object也定义了length且按序存储,此时这个Object就成为了可迭代对象(也叫伪数组),伪数组只是结构与数组相似,但是无法直接使用数组的方法。
二、创建数组
字面量方式(推荐)
语法: 声明变量关键字 变量名 = [元素1,元素2…]
let arr = [1,2,3]
构造函数方式
语法: 通过new关键字,实例化Array对象。
let arr = new Array(1,2,3)
注意:
如果实例化时只传入一个数字n,会创建一个长度为n的数组,该数组包含了n个empty,该数组又称为稀疏数组,即length比实际元素个数要大。
let arr = new Array(3)
console.log(arr) // [empty × 3]
创建元素为empty的数组有什么用呢?
适用于确定数组长度的场景下,如果返回的数据长度过长,会自动忽略,若不足剩余位置仍为empty。
ES6方式
-
Array.of()方法
不限制参数类型,只传一个Number类型参数n时,将其看做一个数据并不会像构造函数一样创建长度为n的空数组。
let arr1 = Array.of(1,2,3) console.log(arr1) // [1,2,3] // 只传一个Number类型参数 let arr2 = Array.of(3) console.log(arr2) // [3]
-
Array.from()方法
该方法主要是将可迭代对象(伪数组)转成一个真正的数组。
const fn = (...args) => { return Array.from(...args) } console.log(fn(1,"name")) // [1,2]
对比几种方式
ES6
的两种方式不常用
,Array.of()适合将一组数据转成数组,Array.from()适合将可迭代对象(类数组、伪数组)转换为真数组。
前两种创建方式效果一致,但字面量方式
书写更为方便,也是开发时最常用
的。
构造函数方式可以在实例化时指定数组的长度,而字面量方式若想创建元素为empty的数组,还需创建空数组后再对数组的length进行赋值。
const arr = new Array(3)
console.log(arr) // [empty x 3]
const arr1 = []
arr1.length = 3
console.log(arr1) // [empty x 3]
三、稀疏数组
什么叫稀疏数组?
例如:[1,2,3,empty x 2]
定义: 如果数组的length大于实际存储的元素个数(其余元素为empty),那么该数组就为稀疏数组。
稀疏数组的作用及使用场景
作用: 初始化时固定数组长度
使用场景: 适用于确定数组长度的场景下,如果返回的数据长度过长,会自动忽略,若不足剩余位置仍为empty。
四、数组方法及分类
ES6以下
-
concat()
合并
两个数组返回: 合并后的数据
不会改变原数据
参数: 可以是数组也可以是1,2这种以,分割的形式,但建议写成数组
注意: ES6可使用解构赋值进行拼接,故concat使用较少。
let arr1 = [1,2,3] let arr2 = [3,4,5] console.log(arr1.concat(arr2)) // [1,2,3,3,4,5] console.log(arr1.concat(1,2)) // [1,2,3,1,2] console.log(arr1) // [1,2,3] console.log(arr2) // [3,4,5]
-
join()
将数组用分隔符拼接
为字符串
返回: 拼接后的字符串
不会改变原数据
参数: 用于拼接的符号,不传参默认为逗号
若想将
字符串
转为数组
,需使用split()let arr = [1,2,3] console.log(arr.join(",")) // "1,2,3" console.log(arr) // [1,2,3]
-
pop()
删除最后一位
元素返回: 删除的元素
会改变原数据
let arr = [1,2,3] console.log(arr.pop()) // 3 console.log(arr) // [1,2]
-
shift()
删除第一位
元素返回: 删除的元素
会改变原数据
let arr = [1,2,3] console.log(arr.shift()) // 3 console.log(arr) // [2,3]
-
push()
添加
元素到最后一位
返回: 操作后的数组的长度
会改变原数据
参数: 任意数据类型的数据
let arr = [1,2,3] console.log(arr.push(1)) // 4 console.log(arr) // [1,2,3,1]
-
unshift()
添加
元素到第一位
返回: 操作后的数组的长度
会改变原数据
let arr = [1,2,3] console.log(arr.unshift(1)) // 4 console.log(arr) // [1,1,2,3]
-
reverse()
翻转
数组返回: 翻转后的数组
会改变原数据
let arr = [1,2,3] console.log(arr.reverse()) // [3,2,1] console.log(arr) // [3,2,1]
-
sort() 数组
排序
返回: 排序后的数组
会改变原数据
参数: 不传参按照默认排序(Number类型按从小到大,字母符号按ASCII码排序)
无参数:
(1)Number类型排序
let arr = [3,6,2] console.log(arr.sort()) // [2,3,6] console.log(arr) // [2,3,6]
(2)非Number类型排序
-
对于非Number类型数据,会先试图将元素转为String以便比较
let arr = ["3","6","2"] console.log(arr.sort()) // ["2","3","6"] console.log(arr) // ["2","3","6"] arr = ["!","b","%","A","a"] console.log(arr.sort()) // ['!', '%', 'A', 'a', 'b'] console.log(arr) // ['!', '%', 'A', 'a', 'b']
-
当元素为字母时,会逐位比较,而不是根据字符串长度排序
let arr = ["ac","abc","acb"] console.log(arr.sort()) // ['abc', 'ac', 'acb'] console.log(arr); // ['abc', 'ac', 'acb']
(3)当元素有undefined时,会将所有undefined排到最后
let arr = [3,undefined,6,2] console.log(arr.sort()) // [2, 3, 6, undefined] console.log(arr) // [2, 3, 6, undefined]
有参数:
sort() 方法不仅按String顺序进行排序,还可以根据其他顺序执行操作。这时就必须为方法提供一个函数参数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。排序函数应该具有两个参数 a 和 b,其返回值如下。
- 如果根据自定义评判标准,a 小于 b,在排序后的数组中 a 应该出现在 b 之前,就返回一个小于 0 的值。
- 如果 a 等于 b,就返回 0。
- 如果 a 大于 b,就返回一个大于 0 的值。
(1) 从小到大排序
function f(a,b) { //排序函数 return (a - b) //返回比较参数 } let arr = [3,1,2,4,5,7,6,8,0,9] arr.sort(f) console.log(arr) // [0,1,2,3,4,5,6,4,7,8,9]
(2) 从大到小排序
function f(a,b) { //排序函数 return (b - a) //返回比较参数 } let arr = [3,1,2,4,5,7,6,8,0,9] arr.sort(f) console.log(arr) // [9,8,7,6,5,4,3,2,1,0]
(3) 根据奇偶数排序
function f(a,b) { //排序函数 let a = a % 2 //获取参数a的奇偶性 let b = b % 2 //获取参数b的奇偶性 if (a == 0) return 1 //如果参数a为偶数,则排在左边 if (b == 0) return -1 //如果参数b为偶数,则排在右边 } let arr = [3,1,2,4,5,7,6,8,0,9] arr.sort(f) console.log(arr) // [3,1,5,7,9,0,8,6,4,2]
(4) 字母排序
-
默认是区分大小写的,大写字母在ASCII码中顺序优先于小写,故排序在前。
let arr = ["aB", "Ab", "Ba", "bA"] arr.sort() console.log(arr) // ["Ab", "Ba", "aB", "bA"]
-
大写字母总在左侧
function f(a,b) { return (a < b) } let arr = ["aB", "Ab", "Ba", "bA"] arr.sort() console.log(arr) // ["Ab", "Ba", "aB", "bA"]
-
不区分大小写
function f(a, b) { let a = a.toLowerCase let b = b.toLowerCase if (a < b) { return 1 // 如需调整大小写位置,返回值取反即可 } else { return -1 } } let arr = ["aB", "Ab", "Ba", "bA"] arr.sort() console.log(arr); //返回数组["aB", "Ab", "Ba", "bA"]
(5) 把浮点数和整数分开显示
// 如需调整左右位置,返回值取反即可 function f(a, b) { if (a > Math.floor(a)) return 1 //如果a是浮点数,则调换位置 if (b > Math.floor(b)) return -1 //如果b是浮点数,则调换位置 } let arr = [4.123, 1.23, 3, 8, 2.87, 5, 3, 7] arr.sort(f) console.log(arr) // [3, 8, 5, 3, 7, 4.123, 1.23, 2.87]
-
-
slice()
截取
指定位置的数组返回: 截取到的数组
不会改变原数据
参数: (startIndex,endIndex) 为开始/结束处索引,startIndex必传,表示从哪个元素开始截取。
注意: 参数可为负数,表示从最后排序的第几位
(1) 若不传endIndex,默认会截取到最后一个元素
let arr = [1,2,3,4,5,2,4,1] console.log(arr.slice(3)) // [4, 5, 2, 4, 1] console.log(arr) // [1,2,3,4,5,2,4,1]
(2) 正常两个参数
let arr = [1,2,3,4,5,2,4,1] console.log(arr.slice(0,3)) // [1, 2, 3] console.log(arr) // [1,2,3,4,5,2,4,1]
(3) 当参数为负数
let arr = [1,2,3,4,5,2,4,1] console.log(arr.slice(-1)) // [1] console.log(arr) // [1,2,3,4,5,2,4,1] // 第四个到倒数第二个 console.log(arr.slice(3,-1)) // [4, 5, 2, 4] console.log(arr) // [1,2,3,4,5,2,4,1]
-
splice()
替换
数组中的元素,也可以删除
、添加
返回: 删除元素组成的数组
不一定会改变原数据,若替换数据与原先一致,数组不变。
参数: (startIndex,num,data1,data2,…)
startIndex:索引(可为负数)
num:删除的长度
data:可为任意数据类型
(1) 替换
// 变成1~8 let arr = [1,2,3,4,5,2,4,1] // 从索引5开始删除三个元素,替换为6,7,8 console.log(arr.splice(5,3,6,7,8)) // [2, 4, 1] console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8]
(2) 删除 不传data
// 变成1~5 let arr = [1,2,3,4,5,2,4,1] // 从索引5开始删除三个元素 console.log(arr.splice(5,3)) // [2, 4, 1] console.log(arr) // [1, 2, 3, 4, 5]
(3) 添加 num为0
// 5后面添加一个5 let arr = [1,2,3,4,5,2,4,1] // 从索引5开始删除三个元素,替换为6,7,8 console.log(arr.splice(5,0,5)) // [] console.log(arr) // [1, 2, 3, 4, 5, 5, 6, 7, 8]
-
indexOf() 从
索引0开始
向后依次查找
数组中指定元素
所在的索引
返回: 若数组中存在此元素,返回所在索引。若不存在返回-1。
不会改变原数据
参数: 可为任意类型
注意: 在对比参数与数组元素时,使用的是全等操作符判断。
let arr = [1,2,3,4,5,6] console.log(arr.indexOf(3)) // 2 console.log(arr.indexOf(9)) // -1 console.log(arr) // [1,2,3,4,5,6]
-
lastIndexOf() 从
索引最后一位开始
向前依次查找
数组中指定元素
所在的索引
返回: 若数组中存在此元素,返回所在索引。若不存在返回-1。
不会改变原数据
参数: 可为任意类型
注意: 在对比参数与数组元素时,使用的是全等操作符判断。
let arr = [1,2,3,4,5,6] console.log(arr.lastIndexOf(3)) // 2 console.log(arr.indexOf(9)) // -1
-
forEach()
循环遍历
数组,对每一项运行给定函数返回: 无
会改变原数据
参数: 一个函数,这个函数中有三个参数,分别为item、index、arr
item: 数组中每个元素
index:索引
arr:原数组
注意: 当item为非对象(Object,Array)时,修改不会生效
let arr = [1,2,3,4,5,6] arr.forEach((item,index,arr) => { item += 1 console.log(index) // 0,1,2...5 console.log(arr) // [1,2,3,4,5,6] }) console.log(arr) // [1,2,3,4,5,6] let arr = [{id:1,name:"ts"},{id:2,name:"aa"},{id:3,name:"bb"}] arr.forEach((item,index,arr) => { item.name = "田本初" console.log(index) // 0,1,2 console.log(arr) // [1,2,3,4,5,6] }) console.log(arr) //
ES6+
-
map()
遍历
数组的每个元素,并对每个元素执行指定的回调函数,然后返回一个新数组
,该数组包含每个回调函数的返回值。返回: 包含每个回调函数的返回值的新数组。
不会改变原数据
参数: (callback(currentValue, index, array), thisArg)
callback
是一个回调函数,用于处理数组的每个元素。它可以接收三个参数:currentValue
:当前正在处理的元素。index
:当前正在处理的元素的索引。array
:调用map
方法的数组本身。
thisArg
是可选的参数,用于指定回调函数内部this
关键字的值。
const numbers = [1, 2, 3, 4, 5]; const squaredNumbers = numbers.map(function(num) { return num * num; }); console.log(squaredNumbers); // [1, 4, 9, 16, 25]
-
filter()
过滤
数组中满足指定条件的元素
并返回一个新的数组
,其中包含满足条件的元素。返回: 符合条件的元素集合。
不会改变原数据
参数: (callback(element, index, array), thisArg)
callback
:用于测试每个元素的函数,它接受三个参数:element
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用filter()
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const evenNumbers = numbers.filter(function(num) { return num % 2 === 0; }); console.log(evenNumbers); // 输出 [2, 4, 6, 8, 10]
妙用:参数传Boolean,意为删除「假值」并留下「真值」。
const array = [0, 1, false, 2, '', 3, null, undefined, NaN, 4, 'hello', 5]; const filteredArray = array.filter(Boolean); console.log(filteredArray); // 输出: [1, 2, 3, 4, 'hello', 5]
-
reduce() 对数组中的每个元素执行指定的回调函数(称为 reducer),并将结果汇总为单个值。该方法可以用于各种累积计算,如求和、求积、拼接字符串等。
返回: 计算结果
不会改变原数据
参数: (callback(accumulator, currentValue, currentIndex, array), initialValue)
callback
:回调函数,用于每个元素执行的逻辑。它接受四个参数:accumulator
:累加器,累积计算的结果。currentValue
:当前正在处理的元素。currentIndex
(可选):当前正在处理的元素的索引。array
(可选):调用reduce()
方法的数组。
initialValue
(可选):初始值,作为第一次调用回调函数时的累加器的初始值。如果未提供初始值,则将使用数组的第一个元素作为初始值,并且从数组的第二个元素开始调用回调函数。
const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }, 0); console.log(sum); // 输出 15
-
every() 检测数组中的所有元素是否满足指定条件。
返回: 如果所有元素都满足条件,则返回
true
;否则返回false
。不会改变原数据
参数: (callback(currentValue, index, array), thisArg)
callback
:用于测试每个元素的函数,它接受三个参数:currentValue
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用every()
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
注意:
every()
方法遍历数组中的每个元素,并对每个元素调用回调函数进行测试。如果所有元素都通过测试(即回调函数返回true
),则every()
方法返回true
;如果有一个元素未通过测试(即回调函数返回false
),则every()
方法立即返回false
。- 如果数组为空,则
every()
方法始终返回true
。
const numbers = [2, 4, 6, 8, 10]; const allEven = numbers.every(function(num) { return num % 2 === 0; }); console.log(allEven); // 输出 true
-
some() 检查数组中是否至少有一个元素满足指定的条件
返回: 当数组中至少有一个元素满足条件时,才返回
true
,否则返回false
。不会改变原数据
参数: (callback(currentValue, index, array), thisArg)
callback
:用于测试每个元素的函数,它接受三个参数:currentValue
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用every()
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
注意: 如果数组为空,则
some()
方法始终返回false
。const numbers = [1, 2, 3, 4, 5]; const hasEven = numbers.some(function(num) { return num % 2 === 0; }); console.log(hasEven); // 输出 true,因为至少有一个元素是偶数
-
find() 查找数组中满足指定条件的第一个
元素
返回: 它接受一个回调函数作为参数,用于定义查找条件,并返回满足条件的第一个元素,如果未找到满足条件的元素,则返回
undefined
。不会改变原数据
参数: (callback(element, index, array), thisArg)
callback
:回调函数,用于测试数组中的每个元素。它接受三个参数:element
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用find()
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
注意:
find()
方法会在数组的每个元素上调用回调函数,直到找到满足条件的元素为止。一旦找到满足条件的元素,find()
方法将立即返回该元素,并且不再继续搜索数组的剩余部分。const numbers = [1, 3, 5, 7, 8, 9, 10]; const firstEven = numbers.find(function(num) { return num % 2 === 0; }); console.log(firstEven); // 输出 8,因为 8 是数组中的第一个偶数
-
findIndex() 查找数组中满足指定条件的第一个元素
索引
返回: 返回满足条件的元素的索引。如果未找到满足条件的元素,则返回
-1
。不会改变原数据
参数: (callback(element, index, array), thisArg)
callback
:回调函数,用于测试数组中的每个元素。它接受三个参数:element
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用findIndex()
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
注意:
findIndex()
方法会在数组的每个元素上调用回调函数,直到找到满足条件的元素为止。一旦找到满足条件的元素,findIndex()
方法将立即返回该元素的索引,并且不再继续搜索数组的剩余部分。const numbers = [1, 3, 5, 7, 8, 9, 10]; const firstEvenIndex = numbers.findIndex(function(num) { return num % 2 === 0; }); console.log(firstEvenIndex); // 输出 4,因为 8 是数组中的第一个偶数,索引为 4
-
fill() 填充数组元素
返回: 修改后的数组
不会改变原数据
参数: (value, start, end)
value
:要用来填充数组的值。start
(可选):起始索引(包括)。默认为0
。end
(可选):结束索引(不包括)。默认为数组的长度。
注意: 如果省略
start
和end
参数,则fill()
方法会用value
填充整个数组。const array = [1, 2, 3, 4, 5]; // 将数组中索引为 2 到索引为 4(不包括)的元素替换为 0 array.fill(0, 2, 4); console.log(array); // 输出 [1, 2, 0, 0, 5]
-
keys()
、values()
、entries()
遍历数组中的索引、值或者键值对返回: 迭代器对象
不会改变原数据
三者唯一的区别是keys()是对
键名
的遍历、values()是对键值
的遍历,entries()是对键值对
的遍历。keys()
const array = ['a', 'b', 'c']; const iterator = array.keys(); for (const key of iterator) { console.log(key); // 输出 0, 1, 2 }
values()
const array = ['a', 'b', 'c']; const iterator = array.values(); for (const value of iterator) { console.log(value); // 输出 'a', 'b', 'c' }
entries()
const array = ['a', 'b', 'c']; const iterator = array.entries(); for (const [index, value] of iterator) { console.log(index, value); // 输出 0 'a', 1 'b', 2 'c' }
静态方法
-
Array.isArray(obj):判断指定对象
是否为数组
返回: 布尔值
不会改变原数据
console.log(Array.isArray([1, 2, 3])); // true console.log(Array.isArray("hello")); // false
-
Array.from(arrayLike[, mapFn[, thisArg]]):从类数组对象或可迭代对象中
创建一个新的数组实例
。可选参数mapFn
可以用于对每个元素进行映射操作。返回: 新数组实例
不会改变原数据
const str = "hello"; const arr = Array.from(str, char => char.toUpperCase()); console.log(arr); // ["H", "E", "L", "L", "O"]
-
Array.of(element1[, element2[, …[, elementN]]]):创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
返回: 新数组实例
不会改变原数据
const arr = Array.of(1, 2, 3); console.log(arr); // [1, 2, 3]
数组方法的总结
改变原数组
pop 、 push 、 unshift 、 shift 、 splice 、 sort 、 reverse
可遍历的方法
forEach、 map、 filter、 reduce、 ervery、 some
返回新数组
concat、 slice、 map、 filter
数组相关场景
一、多维数组降维(数组扁平化)
function flattenArray(arr) {
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []);
}
const arr = [1, [2, 3], [[4, 5], 6]];
const res = flattenArray(arr);
console.log(res); // 输出 [1, 2, 3, 4, 5, 6]
二、数组去重
方法一:reduce(ES6)
const array = [1, 2, 2, 3, 3, 3];
const uniqueArray = array.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
console.log(uniqueArray); // 输出 [1, 2, 3]
方法二:filter(ES6)
const array = [1, 2, 2, 3, 3, 3];
const uniqueArray = array.filter((item, index, arr) => arr.indexOf(item) === index);
console.log(uniqueArray); // 输出 [1, 2, 3]
方法三:Set(ES6)
const array = [1, 2, 2, 3, 3, 3];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // 输出 [1, 2, 3]
方法四:forEach
const array = [1, 2, 2, 3, 3, 3];
const uniqueArray = [];
array.forEach(item => {
if (!uniqueArray.includes(item)) {
uniqueArray.push(item);
}
});
console.log(uniqueArray); // 输出 [1, 2, 3]
三、数组排序
sort()
四、解构赋值
可以将一个数组中的元素解构到多个变量中。
const array = [1, 2, 3];
const [a, b, c] = array;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3
忽略某些元素:使用逗号 , 可以忽略数组中的某些元素。
const array = [1, 2, 3];
const [a, , c] = array;
console.log(a); // 输出 1
console.log(c); // 输出 3
剩余元素:使用剩余运算符 … 可以将数组中剩余的元素赋值给一个新的数组。
const array = [1, 2, 3, 4, 5];
const [a, b, ...rest] = array;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(rest); // 输出 [3, 4, 5]
默认值:可以为解构赋值的变量设置默认值。
const array = [1];
const [a, b = 2] = array;
console.log(a); // 输出 1
console.log(b); // 输出 2,因为数组中没有第二个元素,所以使用了默认值
嵌套解构:可以对嵌套的数组进行解构赋值。
const array = [1, [2, 3], 4];
const [a, [b, c], d] = array;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3
console.log(d); // 输出 4
五、清空数组
方法一:赋值空数组,将数组赋值为空数组 []。
let array = [1, 2, 3];
array = [];
console.log(array); // 输出 []
方法二:使用 length 属性,将数组的 length 属性设置为 0。
let array = [1, 2, 3];
array.length = 0;
console.log(array); // 输出 []
方法三:使用 splice() 方法删除数组的所有元素。
let array = [1, 2, 3];
array.splice(0, array.length);
console.log(array); // 输出 []
方法四:循环调用 pop() 方法直到数组为空。
let array = [1, 2, 3];
while (array.length) {
array.pop();
}
console.log(array); // 输出 []
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)