• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • Array.prototype.flat()

    flat()方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

    语法

    var newArray = arr.flat([depth])
    

    参数

    depth可选
    指定要提取嵌套数组的结构深度,默认值为 1。

    返回值

    一个包含将数组与子数组中所有元素的新数组。

    示例

    扁平化嵌套数组

    var arr1 = [1, 2, [3, 4]];
    arr1.flat(); 
    // [1, 2, 3, 4]
    
    var arr2 = [1, 2, [3, 4, [5, 6]]];
    arr2.flat();
    // [1, 2, 3, 4, [5, 6]]
    
    var arr3 = [1, 2, [3, 4, [5, 6]]];
    arr3.flat(2);
    // [1, 2, 3, 4, 5, 6]
    
    //使用 Infinity,可展开任意深度的嵌套数组
    var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
    arr4.flat(Infinity);
    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    扁平化与数组空项

    flat()方法会移除数组中的空项:

    var arr4 = [1, 2, , 4, 5];
    arr4.flat();
    // [1, 2, 4, 5]
    

    替代方案

    使用reduceconcat

    var arr = [1, 2, [3, 4]];
    
    // 展开一层数组
    arr.flat();
    // 等效于
    arr.reduce((acc, val) => acc.concat(val), []);
    // [1, 2, 3, 4]
    
    // 使用扩展运算符 ...
    const flattened = arr => [].concat(...arr);
    

    reduce + concat + isArray + recursivity

    // 使用 reduce、concat 和递归展开无限多层嵌套的数组
    var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
    
    function flatDeep(arr, d = 1) {
       return d > 0 ? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val), [])
                    : arr.slice();
    };
    
    flattenDeep(arr1, Infinity);
    // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    

    使用堆栈stack

    // 注意:深度的控制比较低效,因为需要检查每一个值的深度
    // also possible w/o reversing on shift/unshift, but array OPs on the end tends to be faster
    var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
    function flatten(input) {
      const stack = [...input];
      const res = [];
      while (stack.length) {
        // 使用 pop 从 stack 中取出并移除值
        const next = stack.pop();
        if (Array.isArray(next)) {
          // 使用 push 送回内层数组中的元素,不会改动原始输入
          stack.push(...next);
        } else {
          res.push(next);
        }
      }
      // 反转恢复原数组的顺序
      return res.reverse();
    }
    flatten(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    
    // 递归版本的反嵌套
    function flatten(array) {
      var flattend = [];
      (function flat(array) {
        array.forEach(function(el) {
          if (Array.isArray(el)) flat(el);
          else flattend.push(el);
        });
      })(array);
      return flattend;
    }
    

    reduce+ concat+ isArray+ recursivity

    var arr = [1, 2, [3, 4, [5, 6]]];
    
    //to enable deep level flatten use recursion with reduce and concat
    function flatDeep(arr) {
       return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val) : val), []);
    };
    
    flatDeep(arr);
    // [1, 2, 3, 4, 5, 6]
    

    Use a stack

    //non recursive flatten deep using a stack
    function flatten(input) {
      const stack = [...input];
      const res = [];
      while (stack.length) {
        // pop value from stack
        const next = stack.pop();
        if (Array.isArray(next)) {
          // push back array items, won't modify the original input
          stack.push(...next);
        } else {
          res.push(next);
        }
      }
      //reverse to restore input order
      return res.reverse();
    }
    
    var arr = [1, 2, [3, 4, [5, 6]]];
    flatten(arr);
    // [1, 2, 3, 4, 5, 6]
    

    Use Generator function

    function* flatten(array) {
        for (const item of array) {
            if (Array.isArray(item)) {
                yield* flatten(item);
            } else {
                yield item;
            }
        }
    }
    
    var arr = [1, 2, [3, 4, [5, 6]]];
    const flattened = [...flatten(arr)];
    // [1, 2, 3, 4, 5, 6]
    

    Please do not add polyfills on this article. For reference, please check: https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500