数组用于存储多个有序的数据
- 数组本质上是以数字为键(从0开始,依次递增),并外加一个会自动增长的 length 属性的对象。
创建数组
方式 1 - 通过字面量创建
// 空数组
let arr1 = [];
let arr2 = [1,2,3];
方式 2 - 使用构造函数 new Array()
let arr1 = new Array(); // 参数为空,得到一个空数组 []
let arr2 = new Array(4); // 参数为一个数值时表示数组的长度,得到 [undefined,undefined,undefined,undefined]
let arr3 = new Array(15, 16, 17); // 参数为多个数值时表示数组中的元素,得到[15,16,17]
方式 3 - Array.of()
ES6 新增语法
let arr = Array.of(1, 'abc', true);
当只有一个参数时,构造函数 Array 会将其作为数组的长度,而不是元素,这很容易造成歧义(因为其他参数数量时,参数都是数组的元素,而不是数组的长度),因此,ES6 新增了 Array.of() 语法来避免这种歧义。
let arr1 = Array.of(2) //[2]
let arr2 = Array.of("2") //["2"]
let arr3 = Array.of(1,"2",{obj: "3"}) //[1,"2",{obj: "3"}]
方式 4 - Array().fill()
用于创建指定数量,元素相同的数组
- Array 的参数为数字
- fill 的参数为元素
Array(9).fill('1')
得到
["1", "1", "1", "1", "1", "1", "1", "1", "1"]
常用的数组操作
数组的API | 功能 | 入参 | 返回值 | 是否改变原数组 |
---|---|---|---|---|
unshift | 在数组头部追加元素 | 新元素 | 数组的新长度 | 改变 |
push | 在数组尾部追加元素 | 新元素 | 数组的新长度 | 改变 |
shift | 移除数组的第一项 | 无 | 被移除的元素 | 改变 |
pop | 移除数组最后一项 | 无 | 被移除的元素 | 改变 |
sort | 数组排序 | 排序规则函数 | 排序后的数组 | 改变 |
reverse | 数组反转 | 无 | 反转后的数组 | 改变 |
fill | 数组覆写 | 新元素,起始下标,终点下标 | 覆写后的数组 | 改变 |
splice | 拼接数组 | 下标,删除数量,新元素 | 移除元素的数组 | 改变 |
slice | 数组截取 | 起始下标,终点下标 | 截取的数组 | 不改变 |
filter | 数组过滤 | 过滤规则函数 | 过滤后的数组 | 不改变 |
reduce | 数组缩减 | 缩减规则函数 | 计算结果 | 不改变 |
toString | 数组转字符串 | 无 | 字符串 | 不改变 |
join | 拼接元素 | 拼接符 | 字符串 | 不改变 |
判断是否为数组 Array.isArray()
let list = [1, 2, 3];
let a = 1;let result1 = Array.isArray(list); // true
let result2 = Array.isArray(a); // false
获取数组的长度 length
let list = [1, 2, 3];
let result = list.length; // 3
修改数组的长度
-
如果
新长度 > 原长度
,多出的部分会填充 null。let arr2 = [21, 22, 23]; arr2.length = 5; // [21,22,23,null,null]
-
如果
新长度 < 原长度
,多出的元素会被删除let arr1 = [11, 12, 13]; arr1.length = 1; // [11]
访问元素 []
通过数组的下标访问
let list = [1, 2, 3];// 访问数组第一个元素
console.log(list[0]); // 打印结果:1// 访问数组最后一个元素
console.log(list[list.length - 1]); // 打印结果:3// 访问数组不存在的下标
console.log(list[5]); // 打印结果:undefined
搜索元素
查找目标元素的下标 indexOf()
从前往后查找,若数组中存在目标元素,则返回目标元素在数组中的第一个下标,如数组中不存在目标元素,则返回 -1
let list = [1, 2, 3];let index1 = list.indexOf(1); // 结果为 0
let index2 = list.indexOf(4); // 结果为 -1
lastIndexOf()
功能类似,但是从后往前查找
let list = [1, 2, 3, 1];let index = list.lastIndexOf(1); // 结果为 3
判断数组是否包含目标元素
方式一:includes()【推荐】
目标数组.includes(目标元素)
[1, 2, 3].includes(2); // true// 第二个参数表示搜索的起始位置,默认为 0 。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为 -4 ,但数组长度为 3 ),则会重置为从 0 开始。
[1, 2, 3].includes(3, 3); // false
方式二:indexOf()
let list = [1, 2, 3];if (list.indexOf(4) === -1) {console.log("list 数组中没有元素 4");
}
查找第一个符合条件的元素 find()
目标数组.find(返回搜索条件的函数)
let list = [1, 2, 3, 3];// 搜索到符合条件的元素,返回该元素
let result1 = list.find((item) => item > 2); // 得到 3// 若无符合条件的元素,返回 undefined
let result2 = list.find((item) => item > 4); // 得到 undefined
查找第一个符合条件的元素的下标 findIndex()
目标数组.findIndex(返回搜索条件的函数)
let list = [1, 2, 3, 3];// 搜索到符合条件的元素,返回该元素的下标
let result1 = list.findIndex((item) => item > 2); // 得到 2// 若无符合条件的元素,返回 -1
let result2 = list.findIndex((item) => item > 4); // 得到 -1
修改元素
目标数组[目标位置的下标] = 新的值
let list = [1, 2, 3];list[1] = 4; // list 变为 [ 1, 4, 3 ]
添加元素
在目标位置添加元素
方式1:splice 【推荐】
目标数组.splice(目标位置的下标, 删除元素的数量, 新元素);
- 返回值为被删除元素组成的数组
let list = [1, 2, 3];// 在下标为 1 的地方添加元素 4
let result = list.splice(1, 0, 4); // list 变为 [ 1, 4, 2, 3 ] , result 的值为 []
方式2:下标赋值
目标数组[目标位置的下标] = 新元素
- 若目标位置的下标 < 数组长度,则是修改元素
- 若目标位置的下标 = 数组长度,则是在数组尾部添加新元素
- 若目标位置的下标 > 数组长度,则 arr.length -1至 index-1之间为空属性,用下标访问时,得到 undefined
在数组头部添加元素 unshift()
即左侧,添加一个或多个元素,返回数组的新长度
let list = [1, 2, 3];// list 变为 [ 0, 0.1, 1, 2, 3 ], result 的值为 5
let result = list.unshift(0, 0.1);
在数组尾部添加元素 push()
即右侧,添加一个或多个元素,返回数组的新长度
let list = [1, 2, 3];// list 变为 [ 1, 2, 3, 4, 5 ], result 的值为 5
let result = list.push(4, 5);
删除元素
删除指定下标的元素 splice
目标数组.splice(指定下标, 1);
let list = [1, 2, 3];// list 变为 [ 1, 3 ], result 的值为 [ 2 ]
let result = list.splice(1, 1);
不推荐使用 delete
let list = [1, 2, 3];// list 变为 [ 1, undefined , 3 ]
delete list[1];
- 目标下标的元素会变为 undefined
- 数组的长度不会发生改变!
删除第一个元素 shift
返回被删除的元素
let list = [1, 2, 3];// list 变为 [ 2, 3 ] , result 的值为 1
let result = list.shift();
删除最后一个元素 pop
返回被删除的元素
let list = [1, 2, 3];// list 变为 [ 1, 2 ] , result 的值为 3
let result = list.pop();
删除指定元素
https://blog.csdn.net/weixin_41192489/article/details/126179580
删除所有元素——清空数组
let list = [1, 2, 3];//方式1
list = []; //方式2
list.length = 0; //方式3
list.splice(0);
拼接元素
用 ,
拼接 toString()
let list = [1, 2, 3];let result = list.toString(); // 结果为 1,2,3
效果与 join()
和 join(',')
相同
用目标字符拼接 join()
目标数组.join(目标字符)
因默认的拼接符为 ,
, 所以 join()
, join(',')
和 toString() 的效果相同。
let list = [1, 2, 3];
// 用 - 进行拼接
let result = list.join("-"); // 结果为 1-2-3
数组排序 sort()
https://blog.csdn.net/weixin_41192489/article/details/116696303
- 对象数组排序
https://blog.csdn.net/weixin_41192489/article/details/111400551
数组过滤 filter()
let list1 = [1, 2, 3];
// 过滤掉数组中小于 1 的元素
let list2 = list1.filter((item) => item > 1); // list2 为 [ 2, 3 ],不会改变 list1
数组反转 reverse()
let list1 = [1, 2, 3];let list2 = list1.reverse(); // list1 和 list2 都为 [ 3, 2, 1 ]
- 手写数组反转
https://blog.csdn.net/weixin_41192489/article/details/116695073
数组合并 concat()
let list1 = [1, 2];
let list2 = [3, 4];let list3 = list1.concat(list2); // list3 为 [ 1, 2, 3, 4 ],list1 和 list2 不变let list4 = [5, 6];// 可同时合并多个数组
let list5 = list1.concat(list2, list4); // list5 为 [ 1, 2, 3, 4, 5, 6 ]
用 push 也可实现数组合并
let list1 = [1, 2];
let list2 = [3, 4];
let list3 = []
list3.push(...list1,...list2); // list3 为 [ 1, 2, 3, 4 ]
数组覆写 fill()
- 第一个参数为填充的内容
- 第二个参数为填充的起始下标(含头)
- 第三个参数为填充的终止下标(不含尾)
let arr = ['a', 'b', 'c'];
// 若只有第一个参数,则所有元素都覆写为第一个参数
arr.fill(7)
//[ 7, 7, 7 ]['a', 'b', 'c'].fill(7, 1, 2)
//[ 'a', 7, 'c' ]
会改变原数组
let list = [1, 2];let result = list.fill(9); // result 和 list 都为 [ 9, 9 ]
数组截取 slice()
不会改变原数组
新数组 = 原数组.slice(开始位置的索引, 结束位置的索引); //注意:包含开始索引,不包含结束索引
- slice() 是浅拷贝,对于引用类型的元素,拷贝的是地址,原数组改变时,会改变新数组
let list = [1, 2, 3];// 从下标 2 开始截取,直到数组末尾
let result1 = list.slice(2); // 结果为 [ 3 ]// 截取最后两个元素
let result2 = list.slice(-2); // 结果为 [ 2, 3 ]// 从下标 1 开始截取(含头),在下标 2 处停止截取(去尾)
let result3 = list.slice(1, 2); // 结果为 [ 2 ]// 起始下标 > 终点下标 时,无法截取到元素
let result4 = list.slice(4, 2); // 结果为 [ ]
数组拼接 splice()
https://blog.csdn.net/weixin_41192489/article/details/116694667
数组缩减 reduce()
可用于数据累积计算(如求和),数据统计,数组降维,数组去重等,详见 https://blog.csdn.net/weixin_41192489/article/details/116661854
数组的遍历
https://blog.csdn.net/weixin_41192489/article/details/140170995
数组的复制
浅拷贝
let list1 = [1, 2, 3];// 浅拷贝 -- 将 list1 中的数组地址,复制到 list2 中
let list2 = list1;// list1 改变时 ,list2 也会同步改变
list1[0] = 4;console.log(list2); // 结果为 [ 4, 2, 3 ]
深拷贝
函数封装 extend
function getType(o) {var _t;return ((_t = typeof o) == "object"? (o == null && "null") || Object.prototype.toString.call(o).slice(8, -1): _t).toLowerCase();
}function extend(destination, source) {for (var p in source) {if (getType(source[p]) == "array" || getType(source[p]) == "object") {destination[p] = getType(source[p]) == "array" ? [] : {};arguments.callee(destination[p], source[p]);} else {destination[p] = source[p];}}
}
使用
let list1 = [1, 2, 3];let list2 = [];// 深拷贝 -- 将 list1 中的数组复制一份,将复制后的数组的地址,存入 list2 中
extend(list2, list1);// list1 改变时 ,list2 不会发生改变
list1[0] = 4;console.log(list2); // 结果为 [ 1, 2, 3 ]
lodash 中的 cloneDeep 可轻松完成深拷贝
let list2 = _.cloneDeep(list1);
以下方式,可对简易数组(无嵌套,元素无正则,undefined,函数等)实现深拷贝:
let arr1 = [1, 2, 3]
// 仅深拷贝第一层,若存在嵌套则不适用
let arr2 = [...arr1]
let arr1 = [1, 2, 3];
let arr2 = [];
for (let i = 0; i < arr1.length; i++) {// 仅深拷贝第一层,若存在嵌套则不适用arr2.push(arr1[i]);
}
// 若元素存在正则,undefined,函数等则不适用
let arr2 = JSON.parse(JSON.stringify(arr1))
数组的去重
https://blog.csdn.net/weixin_41192489/article/details/125988156
数组的交集、差集、补集、并集
https://blog.csdn.net/weixin_41192489/article/details/139855697
伪数组/类数组
https://blog.csdn.net/weixin_41192489/article/details/116642962
【实战】对象数组的分类统计
let Data = [{"province": "四川","boy": 8,"girl": 10},{"province": "湖北","boy": 2,"girl": 8},{"province": "四川","boy": 9,"girl": 6},{"province": "湖北","boy": 4,"girl": 7}
]let dataObj = {}
//遍历数组,item为数组的每一个对象
Data.forEach((item, index) => {//第一次添加该省时,初始化boy和girl的值为0if (dataObj[item.province] == undefined) {dataObj[item.province] = {boy: 0,girl: 0}}// 倘若boy或girl的值为null或undefined,则初始化为0item.boy = item.boy ? item.boy : 0item.girl = item.girl ? item.girl : 0// 按省进行累加统计dataObj[item.province] = {boy: dataObj[item.province].boy + item.boy,girl: dataObj[item.province].girl + item.girl}}
)console.log(dataObj)
此时dataObj的值为
{'四川': {boy: 17,girl: 16},'湖北': {boy: 6,girl: 15}
}