我们待会些flat源码,先分析下数据降维我们怎么去处理?
法一 用flat方法
let ary = [1, [2, [3, [4, 5]]], 6,{name:1}];
console.log(ary.flat(Infinity)) // flat不会改变原来数组
法二: 用join+splite方法 (只针对基本数据类型)
let ary = [1, [2, [3, [4, 5]]], 6, 'sss'];
console.log(ary.join(',').splite(',')) // flat不会改变原来数组
法三: 用递归+reduce
方法
function flatten(ary) {
return ary.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
},[])
}
let ary = [1, 2, [3, 4], [5, [6, 7]]]
flatten(ary)
法四: 用concat
方法
let ary = [1, 2, [3, 4], [5, [6, 7]]]
while (ary.some(Array.isArray)) {
ary = [].concat(...ary); // concat会改变原来数组
}
console.log(ary)
当然还可以用传统递归的方法写,我觉得比较low,所以直接上flat
的源码部分
核心:源码来了
注意:Infinity
表示的无穷打的是一个数
1、简单实现
Array.prototype.myFlat = function(deep = 1) {
let arr = this
return deep > 0 ? arr.reduce((prev, next) => {
return (prev.concat(Array.isArray(next) ? next.flat(deep - 1) : next))
},[]) : arr
}
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
console.log(arr1.myFlat());
2、用forEach
简单实现
// forEach 遍历数组会自动跳过空元素
const eachFlat = (arr = [], depth = 1) => {
const result = []; // 缓存递归结果
// 开始递归
(function flat(arr, depth) {
// forEach 会自动去除数组空位
arr.forEach((item) => {
// 控制递归深度
if (Array.isArray(item) && depth > 0) {
// 递归数组
flat(item, depth - 1)
} else {
// 缓存元素
result.push(item)
}
})
})(arr, depth)
// 返回递归结果
return result;
}
3、用for of
简单实现
// for of 循环不能去除数组空位,需要手动去除
const forFlat = (arr = [], depth = 1) => {
const result = [];
(function flat(arr, depth) {
for (let item of arr) {
if (Array.isArray(item) && depth > 0) {
flat(item, depth - 1)
} else {
// 去除空元素,添加非undefined元素(使用void 0比使用undefined能够减少3个字节)
item !== void 0 && result.push(item);
}
}
})(arr, depth)
return result;
}
4、在forEach基础上增加增加类型校验(完善下)
let arr = [1, [2, 3, [4, 5, [12, 3, "zs"], 7, [8, 9, [10, 11, [1, 2, [3, 4]]]]]]];
//万能的类型检测方法
const checkType = (arr) => {
return Object.prototype.toString.call(arr).slice(8, -1);
}
//自定义flat方法,注意:不可以使用箭头函数,使用后内部的this会指向window
Array.prototype.myFlat = function (num) {
//判断第一层数组的类型
let type = checkType(this);
//创建一个新数组,用于保存拆分后的数组
let result = [];
//若当前对象非数组则返回undefined
if (!Object.is(type, "Array")) {
return;
}
//遍历所有子元素并判断类型,若为数组则继续递归,若不为数组则直接加入新数组
this.forEach((item) => {
let cellType = checkType(item);
if (Object.is(cellType, "Array")) {
//形参num,表示当前需要拆分多少层数组,传入Infinity则将多维直接降为一维
num--;
if (num < 0) {
let newArr = result.push(item);
return newArr;
}
//使用三点运算符解构,递归函数返回的数组,并加入新数组
result.push(...item.myFlat(num));
} else {
result.push(item);
}
})
return result;
}
console.log(arr.myFlat(Infinity)); //[1, 2, 3, 4, 5, 12, 3, "zs", 7, 8, 9, 10, 11, 1, 2, 3, 4];