前言
除了之前聊到的一些数组常用的方法,今天分享一个数组身上也是比较重要的api,就是flat。flat是一个用来让多层数组扁平化的方法,使用起来非常简单,但是我们还需要知道自己如何手写实现这个api,达到同样的效果。在此前,我们需要知道递归这个概念,它在实现很多功能函数时都会被用到,比如实现深拷贝,以及一些规律计算,同样也是实现手写flat的重要一步
递归
递归,简单说就是循环地在函数体内调用自身函数。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止 。
在许多计算函数中也会用到递归,比如计算阶乘,一般也可以通过for循环来实现计算,但是这里就使用递归,来更好的完成计算:
function mul(n){
if( n === 1){
return 1
}
return n*mul(n-1);
}
console.log(mul(5)); //120
要使用递归思想,我们就需要找到运算规律,比如上面计算阶乘,我们知道 5! = 5 * 4!,4! = 4 * 3!,3! = 3 * 2!,2! = 2 * 1;利用这个规律,我们知道n! = n * (n - 1)!,那么我们就可以使用递归。需要注意,使用递归,要明确递归的出口,不然会存在死循环,上面的递归函数中,出口就是当 n === 1 时,停止循环。
也有斐波那契数列,从1,2开始,之后每个数都是前两个数的和,计算第几位数的值时,就可以使用递归计算出结果:
//斐波那契数列
// 1 1 2 3 5 8 13 21 34 55 。。。
function fb(n){
if(n===1 || n ===2){
return 1
}
return fb(n-1)+fb(n-2)
}
console.log(fb(7)); //13
数组扁平化
数组扁平化,就是在遇到多层数组时,我们需要把数组的每一层分解出来,成为返回的新数组内的每个元素。
flat,是官方提供的一个api,可以分解数组想要的层数,接受一个参数,参数是多少,那么就是分解多少层,参数为 Infinity 时,就是分解所有层
let arr = [1,2,[3,4,[5]]]
let newArr1 = arr.flat(1) //分解元素为数组的最外一层
let newArr2 = arr.flat(Infinity)
console.log(newArr1); //[ 1, 2, 3, 4, [ 5 ] ]
console.log(newArr2); //[ 1, 2, 3, 4, 5 ]
手写实现flat
要手写实现flat,这里我们选名叫flatten,我们要知道这是可以被数组直接调用的方法,那么可以将这个方法挂在Array原型(prototype)上。调用方法时,遍历需要扁平化的数组,这里利用this指向调用该方法的数组实例对象。遇到是数组的元素,且传入的参数大于零,那么用该数组元素再次调用函数本身,传入参数为当前参数减1,并将其返回结果与新数组拼接(concat),形成递归;若遇到的不是数组,那么直接push入新数组:
let arr = [1,2,[3,4,[5]]]
Array.prototype.flatten = function(n){
let result = []
for(let i=0;i<this.length;i++){
if(Array.isArray(this[i]) && n > 0){
result = result.concat(this[i].flatten(n - 1))
}else{
result.push(this[i])
}
}
return result
}
console.log(arr.flatten(1)); //[ 1, 2, 3, 4, [ 5 ] ]
总结
在现实开发中,对于我们的算法思维要求很高,许多虽然已经提供的api,但是仍然需要我们知道原理,并能够手动实现它们,这就需要我们有很强的代码思维,需要不断锻炼,所以希望这些内容能够帮助到大家,一起加油。