1 函数的调用
eg1:阶乘算法
var f = function (x) { if (x === 1) { return 1; } else { return x * f(x - 1); } }; function fn(n) { if(n === 1) { return 1; }else{ return n*fn(n-1); } } console.log(fn(10)); console.log(f(10));
eg2:兔子繁衍算法 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
var growRabbit = function(n) { if(n<2) { return n; }else{ return growRabbit(n-1) + growRabbit(n-2); } }; var start1 = new Date().getTime(); console.log(growRabbit(10)); var end1 = new Date().getTime(); console.log("===="+(end1-start1)+ "====");
基于本例斐波那契数列的扩展 动态规划
var growRabbit2 = function(n) { var arr = []; for(var i = 0;i <= n;i++) { arr[i] = 0; } if(n == 1 || n ==2 ) { return 1; }else{ arr[1] = 1; arr[2] = 2; for(var j = 3;j <= n;j++) {//循环将会从3到输入的参数之间进行遍历,将数组的每个元素赋值为前两个元素之和, 循环结束, 数组的最后一个元素值即为最终计算得到的斐波那契数值 arr[j] = arr[j-1] + arr[j-2]; } return arr[n-1]; } //return arr[n-1]; }; var start2 = new Date().getTime(); console.log(growRabbit2(1000000)); var end2 = new Date().getTime(); console.log("===="+(end2-start2)+ "====");
经过反复的测试,如果没用动态规划如果求第50项的时候程序就会卡死,如果用第一种动态规划求第一百万的项数大概是60毫秒左右。
这种通过内部定义一个数组进行存储计算结果的方法大大缩减了程序的效率。类似与java经常使用的内部缓存数组的原理。
基于本例斐波那契数列的扩展 动态规划======迭代版本的斐波那契函数
var growRabbit3 = function(n){ var firstStep = 1; var secondStep = 1; var thirdStep = 1; for(var i = 2; i < n; i++){ thirdStep = firstStep + secondStep; firstStep = secondStep; secondStep = thirdStep; } return thirdStep; }; var start3 = new Date().getTime(); console.log(growRabbit3(1000000)); var end3 = new Date().getTime(); console.log("===="+(end3-start3)+ "===="); 此种动态规划迭代版本的算法更加具有效率,同样第一百万的项数大概只有10毫秒的时间。来描述一下这种算法,大概想台阶一样,把所求的数比作一种台阶,前两个数之和就是第三个数依次迭代
循环(loop),指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。
迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。
遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次。
递归(recursion),指的是一个函数不断调用自身的行为。比如,以编程方式输出著名的斐波纳契数列。
2 对象的调用
var obj1 = { name : "Wunworld", age : 25, Fn : function(n) { if(n === 1) { return 1; }else{ //return n*obj1.Fn(n-1); //return n * this.Fn(n-1);//这种写法不好啦,在里面可以充分利用对象的this啦//这种写法不好啦,在里面可以充分利用对象的this啦 return n * arguments.callee(n-1);//函数内部的arguments对象,有一个callee属性,指向的是函数本身。可以使用arguments.callee在内部调用函数. } } }; var obj2 = { name : "Assassin", Fn : obj1.Fn }; console.log(obj1.Fn(5)); console.log(obj2.Fn(5));//函数的函数名申明需要相同
通过this关键字获取函数执行时的对象中的属性,这样执行obj2.fac时,函数内部便会引用obj2的fac属性。
还可以被任意修改对象来调用,那就是万能的call和apply:
obj3 = {}; console.log( obj1.Fn.call(obj3,5) );//(如果未采用arguments.callee()的调用会产生报错。。。)