手写js flat函数随记

147 阅读1分钟

思路整理

大体脉路

  1. 形参是Number()后的值
  2. 返回值是根据形参来铺开嵌套数组,默认值1,最大值Infinity

代码实现

方法一:shift结合push

/**
* 需要考虑的
* 1. 深拷贝一份数据 
* 2. 数组最大嵌套深度,递归次数不能超过最大嵌套深度
* 3. 形参为Infinity 数组全铺平
* 4. 形参为null NaN 0 负数,数组原样输出
* 5. 形参为undefined 1,数组铺平结果相同
* 6. 如果完全使用es5实现,拓展运算符功能如何实现
*/
Array.prototype.myFlat = function(depth = 1) {
    var datas = this.slice() // TODO
    var maxDepth = getArrayDepth(datas)
    var depth = Number(depth) > maxDepth ? maxDepth : Number(depth)
    if (Number.isNaN(depth) || depth <= 0) {
        return datas
    }
    var result = []
    for (var i = 0; i < datas.length; i++) {
        if (Object.prototype.toString.call(datas[i]) === '[object Array]') {
            var elements = datas[i]
            var delEle = elements.shift()
            elements.length > 0 ? result.push(delEle, ...elements) : result.push(delEle)
        } else {
            result.push(datas[i])
        }
    }
    if (depth > 1) {
        return result.myFlat(depth - 1)
    }
    return result
}

function getArrayDepth(arr) {
    const result = arr.map(function(item) {
        if (Array.isArray(item)) {
            return calcDepth(item)
        } else {
            return 0
        }
    })
    return Math.max(...result)
}

function calcDepth(arr) {
    return arr.reduce(function(acc, curr) {
        if (Array.isArray(curr)) {
            return acc + calcDepth(curr)
        } else {
            return acc
        }
    }, 1)
}

var data = [5, 6, [1, 2], [3], [8, [9]], [3, [4, [5]]], [[[[[7]]]]]]
console.log(data.myFlat(NaN))

方法二:reduce结合concat

Array.prototype.myFlat = function(depth = 1) {
    function flatten(arr, depth) {
        let dpt = Number(depth)
        if (Number.isNaN(dpt) || dpt <= 0) {
            return arr
        } else {
            const result = arr.reduce((acc,curr)=>{
                return acc.concat(Array.isArray(curr) && depth > 1 ? flatten(curr, dpt - 1) : curr)
            }
            , [])
            return result
        }
    }
    return flatten(this, depth)
}