# flat 实现

  • flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, {}, [3, 4, [5, {}, ['abc']]]]
arr1.flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
arr2.flat(Infinity) // [1,  2, {}, 3, 4, 5, {}, 'abc']

# toString 实现

  • toString() 方法返回一个表示该对象的字符串。
  • 也可以用来扁平化,但是只针对基本数据类型
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, {}, [3, 4, [5, {}, ['abc']]]]
arr1.toString().split(',') // ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
// 1. 无法针对非基本数据类型,如果有其他类型则会很麻烦
arr2.toString().split(',') // ['1', '2', '[object Object]', '3', '4', '5', '[object Object]', 'abc']
// 2. 最后再恢复成数字类型
arr2.toString().split(',').map(item => +item) // [1, 2, NaN, 3, 4, 5, NaN, NaN]

# join 实现

  • join 实现也只针对基本类型
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, {age: 16}, [3, 4, [5, {}, ['abc']]]]
arr1.join('|').split(/(?:,|\|)/g).map(item => +item) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// 1. 无法针对非基本数据类型
arr2.join('|').split(/(?:,|\|)/g) // ['1', '2', '[object Object]', '3', '4', '5', '[object Object]', 'abc']
// 2. 最后再转成数字类型
arr2.join('|').split(/(?:,|\|)/g).map(item => +item) // [1, 2, NaN, 3, 4, 5, NaN, NaN]

# JSON.stringify 实现

  • JSON.stringify 是可以实现扁平化的, 但是最后要转换成原来的类型是比较麻烦的
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, {age: 16}, [3, 4, [5, {}, ['abc']]]]
// 1. 如果都是数字类型就比较简单,但如果有字符串类型或其他类型则需要以下判断 比较麻烦
JSON.stringify(arr1).replace(/(\[|\])/g, '').split(',').map(item => +item) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// 2. 这样扁平化之后,其他类型则是比较麻烦
JSON.stringify(arr2).replace(/(\[|\])/g, '').split(',') // ['1', '2', '{"age":16}', '3', '4', '5', '{}', '"abc"']

# for 循环递归 实现

# 函数递归

  • 使用递归来循环变量实现扁平化
function flat(val, newArr = []) {
  for (let i = 0; i < val.length; i++) {
    if (!Array.isArray(val[i])) newArr.push(val[i])
    else flat(val[i], newArr)
  }
  return newArr
}
  • 测试
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, { age: 16 }, [3, 4, [5, {}, ['abc']]], [6, 7]]
flat(arr1) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
flat(arr2) // [1, 2, {age: 16}, 3, 4, 5, {}, 'abc', 6, 7]

# 闭包递归

  • 使用闭包形式递归实现扁平化
  • 这里说几个函数前面符号的意思
    • ! 对返回值的真假取反
    • + 、- 是对返回值进行数学运算
    • ~ 按位非运算符,反转操作数的位,对返回值进行按位取反
    • ; 是为了防止代码压缩时,前面代码没写 ; 造成报错。
  • 在函数前面加这些或者在括号中,那么此函数就变成了函数表达式,函数表达式就可以立即执行
// 立即执行函数,转为表达式
~ function () {
  function flat() {
    const result = []
    const fn = (arr) => {
      for (let i = 0; i < arr.length; i++) {
        if (!Array.isArray(arr[i])) result.push(arr[i])
        else fn(arr[i])
      }
    }
    fn(this)
    return result
  }
  Array.prototype.flat = flat
}()
  • 测试
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, { age: 16 }, [3, 4, [5, {}, ['abc']]], [6, 7]]
arr1.flat() // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
arr2.flat() // [1, 2, {age: 16}, 3, 4, 5, {}, 'abc', 6, 7]

# while & some 实现

function flat(val) {
  while (val.some(item => Array.isArray(item))) 
    val = [].concat(...val)
  return val
}
  • 测试
const arr1 = [1, 2, 3, [4, 5, [6, 7, [8, 9, [10]]]]]
const arr2 = [1, 2, { age: 16 }, [3, 4, [5, {}, ['abc']]]]
flat(arr1) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
flat(arr2) // [ 1, 2, { age: 16 }, 3, 4, 5, {}, 'abc' ]