JavaScript Array Flatten 与递归使用介绍

如何用 JavaScript 将 [1,2,3,[4,5, [6,7]], [[[8]]]] 这样一个 Array 变成 [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) 的时候,调用函数自身,通过传参数的形式进行递归。只是在重构 Array.js 的时候,就觉得既然是框架,那么多抽象出来的东西不用,是不是太浪费了。所以,最好调用已经抽象出来的静态函数,而不是又重新一遍。这里有 for 循环,也就是说我们会需要有 each。结果呢?四个字,不好实现。因为我们始终要创建一个数组,最终 return 这个新的数组,得重新抽出来一个函数来调。这不就违背了初衷?

网上瞄了一下,最终盯在 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;
});
}

当然,这里面还需要另外一个抽象出来的函数,来处理 for 循环,就是我们的 each 函数了。顺路在 flatten 中,带出这个 each 函数吧,学习了 jQuery 的做法,加入原生支持;当然,还可以处理纯对象,而不仅仅是数组:


代码如下:

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的。囧。似乎是一个很大的改变。需要平衡一下了。

(0)

相关推荐

  • JavaScript中的迭代器和生成器详解

    处理集合里的每一项是一个非常普通的操作,JavaScript提供了许多方法来迭代一个集合,从简单的for和for each循环到 map(),filter() 和 array comprehensions(数组推导式).在JavaScript 1.7中,迭代器和生成器在JavaScript核心语法中带来了新的迭代机制,而且还提供了定制 for-in 和 for each 循环行为的机制. 迭代器 迭代器是一个每次访问集合序列中一个元素的对象,并跟踪该序列中迭代的当前位置.在JavaScript中

  • JavaScript的递归之递归与循环示例介绍

    递归与循环 对于不同类型的需要重复计算的问题,循环和递归两种方法各有所长,能给出更直观简单的方案.另一方面,循环和递归的方法可以互相转换.任何一个循环的代码都可以用递归改写,实现相同的功能:反之亦然.在不失去其普遍性的前提下,可以把循环和递归分别用下列伪代码概括. 伪代码格式说明:循环采用while形式:变量不加定义:赋值用:=:条件表达式和执行的语句都写成函数的形式,圆括号内写上相关的值.其他语法方面,尽量接近Javascript的规范. 复制代码 代码如下: //pseudo code of

  • Javascript 高性能之递归,迭代,查表法详解及实例

    Javascript 高性能之递归,迭代,查表法详解 递归 概念:函数通过直接调用自身,或者两个函数之间的互相调用,来达到一定的目的,比如排序,阶乘等 简单的递归 阶乘 function factorial(n) { if (n == 0) { return 1; } else { return n * factorial(n - 1); } } 递归实现排序 /* 排序且合并数组 */ function myMerge(left, right) { // 保存最后结果的数组 var res =

  • 总结javascript中的六种迭代器

    1.forEach迭代器 forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化 //forEach迭代器 function square(num){ document.write(num + ' ' + num*num + '<br>'); } var nums = [1,2,3,4,5,6,7,8]; nums.forEach(square); 在浏览器中输出的结果是: 2.every迭代器 every方法接受一个返回值为布尔类型的函数,

  • JS中递归函数

    编程语言中,函数Func(Type a,--)直接或间接调用函数本身,则该函数称为递归函数.递归函数不能定义为内联函数. 递归函数: function factorical(num){ if(num<=1){ return 1; } else{ return num*factorical(num-1); } } factorial(2)//2 这个递归函数就是用函数来调用函数本身,但是这样真的好吗,好 接下来看这里 var another=factorical; factorical=null;

  • js中递归函数的使用介绍

    下面我们就做一个10以内的阶乘试试看吧: js中递归函数的使用 function f(num){ if(num alert("10!的结果为:"+f(10)); [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 递归函数的调用就说这么多了 js递归函数调用自身时的保险方式. 来自js高级程序设计 一个典型阶乘递归函数: 复制代码 代码如下: function fact(num){ if (num<=1){ return 1; }else{ return num*fact

  • javaScript数组迭代方法详解

    本文为大家介绍了javaScript数组迭代方法,供大家参考,具体内容如下 每个方法都接收两个参数:要在每一项上运行的函数  和  (可选的)运行该函数的作用域对象. 传入这些方法中的函数会接收三个参数:数组项的值,该项在数组中的位置,数组对象本身. forEach()  对数组中的每一项运行 给定函数.该方法没有返回值. every()  对数组中的每一项运行 给定函数,如果数组的每一项都返回true,则返回true. some()  对数组中的每一项运行 给定函数,如果数组的任意一项返回tr

  • 浅谈javascript 迭代方法

    五个迭代方法 都接受两个参数:要在每一项上运行的函数 和 运行该函数的作用域(可选) every():对数组中的每一项运行给定函数.如果函数对每一项都返回true,则返回true.         filter():对数组中的每一项运行给定函数.返回该函数会返回true的项组成的数组.         forEach():对数组中每一项运行给定函数.该函数没有返回值.         map():对数组中每一项运行给定函数.返回每次函数调用的结果组成的函数.         some():对数组

  • JS的数组迭代方法

    本文实例讲述了JS的数组迭代方法.分享给大家供大家参考.具体实现方法如下: <!doctype html> <html> <head lang="zh"> <meta charset="utf-8"> <title>js数组迭代</title> <meta name="renderer" content="webkit"> <script

  • JavaScript 语言的递归编程

    题目:从1累加一直加到100的和是多少? 非递归的循环写法: 复制代码 代码如下: 1run: function() { 2 var sum = 0; 3 for(var i=1;i<=100;i++) { 4 sum = sum + i; 5 } 6 console.log(sum); 7} 递归的写法: 复制代码 代码如下: var testCase = { sum: 0, run: function(n) { if(n>=100) { return 100; } else { sum =

  • js数组的五种迭代方法及两种归并方法(推荐)

    js数组的五种迭代方法及两种归并方法(推荐) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ht

  • JS 树形递归实例代码

    复制代码 代码如下: var l=json.length; var arr = []; for(var i = 0; i < l; i++){ (function(){ var jsonArray =arguments[0]; for(var k in jsonArray){ if(k.indexOf('children') != -1 && jsonArray[k] != null){ arguments.callee(jsonArray[k]); } else{ if(k ==

  • js 数组实现一个类似ruby的迭代器

    分为如下几节: ·基本实现 ·在迭代中引用原来的对象,或者直接改变数组的值而不是返回一个新数组 ·向迭代传入无限多的参数 ·基本实现 今天突然发现js的数组处理起来真是麻烦,代码一些就是一大堆,相比起ruby的迭代器来真是逊色不少,主要是要写的代码太多了,也许是js有特殊的处理数组的方式,真是我不知道而已,但是我真的想自己给js实现一个类似ruby的迭代器的东东,而且实现起来也不难,那就开始动手吧. 真的应该庆幸js是动态语言啊,如果是静态语言,实现起来很不方便(别说要我重新定义一个继承自arr

随机推荐