JavaScript 数组扁平化与递归实现解析

作者:函数茶馆时间:2026-10-26 15:20:59浏览:152

本文探讨如何使用 JavaScript 递归算法实现数组扁平化,从基础循环到框架级抽象。通过解析 flatten、inject 及 each 函数的协作机制,展示如何利用原型方法优化代码结构,提升代码复用性与可读性。

数组扁平化问题概述

如何将包含嵌套数组如 [1,2,3,[4,5, [6,7]], [[[8]]]] 的数据结构转换为单层数组 [1,2,3,4,5, 6,7,8]?这一过程通常被称为数组扁平化(Array Flatten)。



基础递归实现方案

解决此类嵌套问题,递归是常用的编程手段。正如某些资料所述,“递归是一种强大的编程技术”,它并非 JavaScript 独有。尽管递归概念可能复杂,但在处理嵌套数据结构时,其逻辑相对直观且适用。此前有开发者通过简单递归实现了该功能,可作为基础示例参考。


具体实现代码如下:

 
flatten: function(ac){
var array = [];
var group = this.arr;
if(ac) group = ac;
for (var i = 0; i < group.length; i++){
if(group[i] instanceof Array){
array = array.concat(this.flatten(group[i]));
}else{
array = array.concat(group[i]);
} 
} 
return array;
} 

在判断元素是否为数组时(if(group[i] instanceof Array)),函数调用自身并传入当前子数组进行递归。然而,在重构框架代码时,若重复编写此类逻辑则显得冗余。理想做法是直接调用已抽象好的静态函数,而非重新实现。由于此处涉及 for 循环,理论上应利用已有的 each 方法。但问题在于,我们需要始终创建并返回一个新数组,这导致难以直接复用现有抽象,反而增加了代码复杂度,违背了封装初衷。



框架级抽象与优化

查阅相关资料后,发现关键在于对 prototype 的利用。其思路是抽象出一个处理递归增量的函数,再基于该函数实现递归逻辑。这种设计体现了框架的核心价值。以下是处理递归增量的函数实现:


具体代码示例如下:

 
function inject(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index);
}); 
return memo;
} 

基于上述抽象,flatten 函数的最终实现如下,代码结构更为优雅:


具体代码示例如下:

 
function flatten() {
return this.inject([], function(array, value) {
if (Object.isArray(value))
return array.concat(value.flatten());
array.push(value);
return array;
}); 
} 

each 函数与原生支持扩展

此外,还需一个处理循环的抽象函数,即 each 函数。借鉴 jQuery 的做法,将其加入原生支持中,使其不仅能处理数组,还能处理纯对象。以下是 each 函数的实现代码:


具体代码示例如下:

 
each: function (callback, bind) {
var isObject = arale.typeOf(this.obj) === 'object',
i = 0,
key;
if (isObject) {
var obj = this.obj;
for (key in obj) {
if (callback.call(bind, key, obj[key]) === false) {
break;
} 
} 
} else {
var arr = this.obj;
if (Array.prototype.forEach) {
// 用户 return false; 的时候还会继续执行
// 原生的很囧,去还是舍呢? marked TODO;
return [].forEach.call(arr, callback, bind);
}; 
for (var value = arr[0], length = arr.length; i < length && callback.call(bind, i, value) !== false; value = arr[++i]) {};
} 
} 

近期在 JavaScript 开发上投入较多精力,相关文章及团队内部博客内容多集中于 JS 领域。这标志着技术重心的显著转移,后续需适当平衡其他技术方向的学习与实践。

作者最新文章