--- title: Array.prototype.flat() slug: Web/JavaScript/Reference/Global_Objects/Array/flat tags: - JavaScript - 原型 - 参考 - 数组 - 方法 translation_of: Web/JavaScript/Reference/Global_Objects/Array/flat --- <div>{{JSRef}}</div> <p><code><strong>flat()</strong></code> 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。</p> <div>{{EmbedInteractiveExample("pages/js/array-flat.html")}}</div> <h2 id="语法">语法</h2> <pre class="syntaxbox notranslate"><var>var newArray = arr</var>.flat([<var>depth]</var>)</pre> <h3 id="参数">参数</h3> <dl> <dt><code>depth</code> {{optional_inline}}</dt> <dd>指定要提取嵌套数组的结构深度,默认值为 1。</dd> </dl> <h3 id="返回值">返回值</h3> <p>一个包含将数组与子数组中所有元素的新数组。</p> <h2 id="示例">示例</h2> <h3 id="扁平化嵌套数组">扁平化嵌套数组</h3> <pre class="notranslate">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,可展开任意深度的嵌套数组 <code>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]</code></pre> <h3 id="扁平化与数组空项">扁平化与数组空项</h3> <p><code>flat()</code> 方法会移除数组中的空项:</p> <pre class="brush: js notranslate">var arr4 = [1, 2, , 4, 5]; arr4.flat(); // [1, 2, 4, 5]</pre> <h2 id="替代方案">替代方案</h2> <h3 id="使用_reduce_与_concat">使用 <code>reduce</code> 与 <code>concat</code></h3> <pre class="notranslate"><code>var arr = [1, 2, [3, 4]]; // 展开一层数组 arr.flat(); // 等效于 arr.reduce((acc, val) => acc.concat(val), []); // [1, 2, 3, 4] // 使用扩展运算符 ... const flattened = arr => [].concat(...arr);</code></pre> <h3 class="brush: js" id="reduce_concat_isArray_recursivity">reduce + concat + isArray + recursivity</h3> <pre class="brush: js notranslate"><code>// 使用 reduce、concat 和递归展开无限多层嵌套的数组 var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]]; </code> <code class="language-js"><span class="keyword token">function</span> <span class="function token">flatDeep</span><span class="punctuation token">(</span><span class="parameter token">arr<span class="punctuation token">,</span> d <span class="operator token">=</span> <span class="number token">1</span></span><span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="keyword token">return</span> d <span class="operator token">></span> <span class="number token">0</span> <span class="operator token">?</span> arr<span class="punctuation token">.</span><span class="function token">reduce</span><span class="punctuation token">(</span><span class="punctuation token">(</span><span class="parameter token">acc<span class="punctuation token">,</span> val</span><span class="punctuation token">)</span> <span class="operator token">=></span> acc<span class="punctuation token">.</span><span class="function token">concat</span><span class="punctuation token">(</span>Array<span class="punctuation token">.</span><span class="function token">isArray</span><span class="punctuation token">(</span>val<span class="punctuation token">)</span> <span class="operator token">?</span> <span class="function token">flatDeep</span><span class="punctuation token">(</span>val<span class="punctuation token">,</span> d <span class="operator token">-</span> <span class="number token">1</span><span class="punctuation token">)</span> <span class="punctuation token">:</span> val<span class="punctuation token">)</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="punctuation token">]</span><span class="punctuation token">)</span> <span class="punctuation token">:</span> arr<span class="punctuation token">.</span><span class="function token">slice</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="punctuation token">}</span><span class="punctuation token">;</span></code> <code> flatDeep(arr1, Infinity); // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]</code></pre> <h3 id="forEachisArraypushrecursivity">forEach+isArray+push+recursivity</h3> <pre class="brush: js notranslate">// 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; } // 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元素 item !== void 0 && result.push(item); } } })(arr, depth) return result; } </pre> <h3 id="使用堆栈stack">使用堆栈stack</h3> <pre class="notranslate">// 无递归数组扁平化,使用堆栈 // 注意:深度的控制比较低效,因为需要检查每一个值的深度 // 也可能在 shift / unshift 上进行 w/o 反转,但是末端的数组 OPs 更快 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]</pre> <pre class="notranslate">// 递归版本的反嵌套 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; }</pre> <h3 id="Use_Generator_function">Use <code>Generator</code> function</h3> <pre class="notranslate"><code>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]</code></pre> <p>Please do not add polyfills on this article. For reference, please check: <a href="https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500">https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500</a></p> <h2 id="Specifications">Specifications</h2> <table> <tbody> <tr> <th scope="col">Specification</th> <th scope="col">Status</th> <th scope="col">Comment</th> </tr> <tr> <td><a href="https://www.ecma-international.org/ecma-262/10.0/index.html#sec-array.prototype.flat">ECMAScript 2019</a></td> <td>Finished</td> <td>Initial definition</td> </tr> </tbody> </table> <h2 id="浏览器兼容性">浏览器兼容性</h2> <div> <p>{{Compat("javascript.builtins.Array.flat")}}</p> </div> <h2 id="参见">参见</h2> <ul> <li>{{jsxref("Array.prototype.flatMap()")}}</li> <li>{{jsxref("Array.prototype.map()")}}</li> <li>{{jsxref("Array.prototype.reduce()")}}</li> <li>{{jsxref("Array.prototype.concat()")}}</li> </ul>