伪代码格式说明:循环采用while形式;变量不加定义;赋值用:=;条件表达式和执行的语句都写成函数的形式,圆括号内写上相关的值。其他语法方面,尽量接近Javascript的规范。 复制代码 代码如下: //pseudo code of a loop //while形式 function loop(arguments){ //结果的初始值 result:=initial_value;
籍比较两段代码,可以看出循环和递归具有相似的构成,通过改变顺序和适当的变换,任何循环都可以用递归的方式实现。程序简单时,这种转换很容易看出。比如下面这个简单的累计求和函数: 复制代码 代码如下: //loop function sum(num){ var result=1; while (num>1){ result+=num; num--; } return result; }
对应的递归形式:
复制代码 代码如下: //recursion function sum2(num){ if (num>1){ return num+sum(num-1); }else{ return 1; } }
反之,大部分递归程序也可以直接由循环来实现。下面是求最大公约数的循环形式的函数。 复制代码 代码如下: function gcd2(a, b){ var temp; if (a<b){ temp=a; a=b; b=temp; } var c=a%b; while (c!==0){ a=b; b=c; c=a%b; } return b; }
我们再通过一个例子来实践上面观察得出的结论。HTML5为Document和Element新定义了一个方法getElementsByClassName(names),返回具有给定class值的所有elements。包括Firefox3在内的一些浏览器已经支持该方法。下面我们先用递归的方法给出一个功能较弱的版本,然后再用循环的方法重写它。 复制代码 代码如下: var getElementsByClass={};
//elem为一个HTMLElement //name为单个class名 //返回包含elem下所有class属性包含给定名称的element的数组 getElementsByClass.recursion1=function (elem, name){ var list=[]; function getElements(el){ if (el.className.split(" ").indexOf(name)>-1){ list.push(el); } for (var i=0, c=el.children; i<c.length; i++){ getElements(c[i]); } } getElements(elem); return list; }
采用循环的版本: 复制代码 代码如下: getElementsByClass.loop1 = function(elem, name){ //use a js array as the basis of a needed stack var stack = []; stack.get = function(){ return stack[stack.length - 1]; }
var list = []; //the business logic part. put the eligible element to the list. function testElem(el){ if (el.className.split(" ").indexOf(name) > -1) { list.push(el); } } //check the root element testElem(elem); //initialize the stack stack.push({ pointer: elem, num: 0 }); var parent, num, el; while (true) { parent = stack.get(); el = parent.pointer.children[parent.num]; if (el) {//enter a deeper layer of the tree testElem(el); stack.push({ pointer: el, num: 0 }); } else {//return to the upper layer if (stack.pop().pointer === elem) { break; } else { stack.get().num += 1; } } }