数组是 js 中常见的对象,关于数组的操作很多,作为一个前端攻城狮,应该要能通过灵活应用其内置属性和方法,来解决一系列数组处理问题
初始化数组
- 构造函数方法
var arr = new Array(3)
var arr = new Array('a','b','c')
var arr = Array(3)
- 字面量方法 //无法指定成员个数
var arr = ['a','b','c']
数组检查和转化
检查数组类型
let arr = [];
// 1.ES5的isArray方法
Array.isArray(arr);
// 2.constructor指向对象实例的构造函数
arr.constructor === Array;
// 3.instanceof原理同2
arr instanceof Array;
// 4.利用Object的原型方法toString判断(必须是Object原型方法,array和function均重写了这个方法)
// toString方法返回反映这个对象的字符串
//可以用来区分各种类型,但是无法判断自定义对象类型,此时可用2.3方法判断自定义类型
Object.prototype.toString.call(arr) === "[object Array]";
数组转化问题
数组转 String—join(separator)
// 注意区别使用空格和空值
arr.join(" ");
String 转数组—split(separator)
// 根据separator来分割字符串,每一项作为数组的一个值
str.spilt(",");
对象转数组
let obj = { name: "jacksonzhou", age: 23 };
Object.keys(obj); // [name,age]
Object.values(obj); // ['jacksonzhou',23]
Object.entries(obj); // [[name,'jacksonzhou'],[age,23]]
数组转对象
Object.assign({},[1,2]) // 转成{0:1,1:1}
{...['a','b','c']} // 转成{0:'a',1:'b',3:'c'}
// es10的api,浏览器暂不支持
Object.fromEntries([name,'jacksonzhou'],[age,23])
类数组转化为数组
类数组定义:不具有数组所具有的方法,但具有 length 属性,其他属性值为非负整数;常见的类数组有 arguments 对象和 DOM 方法的返回结果(document.getElementsByTagName())
// 使用Array原型方法slice
Array.prototype.slice.call(arguments)
// from方法将类似数组或可迭代对象创建为数组
Array.from(arguments)
// ... (扩展运算符)将类数组扩展为一个列表??(列表实际上是啥?),再定义为数组。
[...arguments]
// 借助对象+indexOf,思路是遍历数组,将每一个值标记为属性,将出现一次的值加入新数组;
//一旦obj.indexOf(i)不为-1,说明重复了,不将它加入新数组
针对数组某项的操作
判断是否包含值
// indexOf
[1, 2, 3]
.indexOf(2) // 1(其对应索引),不存在则为-1
[
// includes
(1, 2, 3)
].includes(2) // true
[
// find
(1, 2, 3)
].find((i) => {
i === 3;
}) // 3,无值返回undefined
[
// findIndex
(1, 2, 3)
].findIndex((i) => {
i === 3;
}); //2,返回索引,无值返回-1
给每一项设置统一值
[1, 2, 3].fill(5); // [5,5,5]
每一项是否满足
[1, 2, 3].every((i) => {
return i > 2;
}); // false
有一项满足
[1, 2, 3].some((i) => {
return i > 2;
}); // true
计算每一项出现的次数
// 数组遍历+借助对象+属性标记+值计数
过滤数组
[1, 2, 3, 4, 5]
.filter((i) => {
return i > 2;
}) // [3,4,5]
[
// 过滤空值
(1, 2, null, 3, 0, false, 4, undefined, "", 5)
].filter(Boolean)
[
// [1,2,3,4,5],但不过滤空的引用类型,比如{}、[]
("1", "2", "3")
].map(parseInt) ===
// 输出[1, NaN, NaN]
["1", "2", "3"].map((item, index) => parseInt(item, index));
- 简易实现代码
Array.prototype.filterz = function (fn) {
let arr = this;
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (fn(arr[i])) {
newArr.push(arr[i]);
}
}
return newArr;
}[(1, 2, 3, 4, 5)].filterz((i) => {
return i > 2;
});
重装数组
[1, 2, 3].map((i) => {
return "我是" + i;
});
数组乱序
let arr = [1,2,3,4,5,6]
arr.sort(function(){
return Math.random()-0.5
})
数组去重
Map 对象+过滤器 filter
Map 数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
function unique(arr) {
const res = new Map();
return arr.filter((a) => !res.has(a) && res.set(a, 1));
}
set(集合)去重
Set 数据结构,它类似于数组,但是成员的值都是唯一的,没有重复的值。
Array.from(new Set([1,2,2,3]))
[...new Set([1,2,2,3])]
直接使用数组去重
function unique2(arr) {
let newArr = []
for(let i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i])===-1)newArr.push(arr[i])
}
return newArr
}
对象数组去重
let json1 = [
{ id: 1, name: "a" },
{ id: 2, name: "b" },
{ id: 3, name: "c" },
];
let json2 = [
{ id: 1, name: "a" },
{ id: 2, name: "b" },
{ id: 4, name: "d" },
];
let json = json1.concat(json2); //两个数组对象合并
let newJson = []; //盛放去重后数据的新数组
for (item1 of json) {
//循环json数组对象的内容
let flag = true; //建立标记,判断数据是否重复,true为不重复
for (item2 of newJson) {
//循环新数组的内容
if (item1.id == item2.id) {
//让json数组对象的内容与新数组的内容作比较,相同的话,改变标记为false
flag = false;
}
}
if (flag) {
//判断是否重复
newJson.push(item1); //不重复的放入新数组。 新数组的内容会继续进行上边的循环。
}
}
console.log("newJson", newJson);
扁平化数组
// flat是ES10的api, n表示维度, n为 Infinity 时维度为无限大
[[1,2],3].flat(2) // [1,2,3]
[1,[2,3,[4,[...]]]].flat(Infinity) // [1,2,3,4,...]
// 利用toString()实现
let arr = [1,[2,3,[4,5]]]
arr.toString().split(',').map(item=>{
+item // 强制转换为数字类型
})
// 使用迭代的方式实现
let arr = [1, 2, [3, 4, 5, [6, 7], 8]]
function flat(arr) {
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr) // 将数组型数值追加,并重复追加,知道没有数组型数据
}
return arr
}
flat(arr)
// 使用递归的方式实现
const flat = arr => arr.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flat(cur)] : [...acc, cur]), [])
排序
// sort--关于排序有太多算法知识点,这里只简单实现升序降序,后续再总结相关算法吧~
[1, 3, 2]
.sort((a, b) => {
a - b;
}) // 升序
[(1, 3, 2)].sort((a, b) => {
b - a;
}); // 降序
求最值
// Math.max/min
Math.max(...[1, 2, 3]); // ...将数组转化为参数列表,供max方法使用
Math.max.apply(this, [1, 2, 3])[
// 利用apply可带数组参数
// === Math.max.call(this,...[1,2,3])
// reduce--累加器
(1, 2, 3, 5)
].reduce((pre, cur) => {
return Math.max(pre, cur);
}, 0);
// pre 指上一次return的值,cur指当前值,0指初始值
reducer 累加器原理
function reduce (arr, fn, initVal) {
for (let i = 0; i < arr.length; i++) {
initVal = fn(initVal, arr[i])
}
return initVal
}
let newArr = reduce(arr, (sum, cur) => {
return sum + cur
}, 5)
console.log(newArr)
求和
// 遍历求和
let sum = 0;
[1, 2, 3].map((i) => {
sum += i;
});
console.log(sum);
// reduce -- 累加器
let sum = [1, 2, 3].reduce((prev, current) => {
return prev + current;
}, 0);
// 0 是初始值, prev 是先前return的值,current是当前值
合并
// concat--不会改变原数组,返回一个数组副本
let newArr = arr.concat([1,2,3])
// push--会改变原数组
arr.push([1,2,3])
// ...
[...[1,2,3],...[4,5]]
其他
- 请把两个数组 [‘A1’, ‘A2’, ‘B1’, ‘B2’, ‘C1’, ‘C2’, ‘D1’, ‘D2’] 和 [‘A’, ‘B’, ‘C’, ‘D’],合并为 [‘A1’, ‘A2’, ‘A’, ‘B1’, ‘B2’, ‘B’, ‘C1’, ‘C2’, ‘C’, ‘D1’, ‘D2’, ‘D’]
// 先给第二个数组的值加个数字,让其能按顺序排序,然后再遍历数组去掉第二个数组的值加上的数字
let a1 = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
let a2 = ['A', 'B', 'C', 'D'].map((item) => {
return item + 3
})
let a3 = [...a1, ...a2].sort().map((item) => {
if(item.includes('3')){
return item.split('')[0]
}
return item
})
栈和队列操作
栈操作
- push()
- pop()
队操作
- push()
- shift() // 区别一下 unshift()
扩展运算符…
- 复制数组
let arr1 = [1, 2, 3];
let arr2 = arr1; // 仅是复制引用,修改arr2会影响arr1
let arr2 = [...arr1]; // 实际上等同于重新声明赋值
- 转为函数参数
Math.max(...[-1, 1, 1001, -52]); // 1001