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()的調用會產生報錯。。。)