文章目录
- 一、什么是递归函数
- 二、递归函数实现的基本思路
- 三、递归函数的注意点
- 四、递归案例
- 2.1、1~n的累加和
- 2.2、求n的阶乘
- 2.3、递归求斐波那契数列
- 五、经典面试题以及推荐用法
一、什么是递归函数
简单来说,递归函数就是一个函数直接或间接地调用自身
二、递归函数实现的基本思路
- 设定好函数的功能(包括参数和返回值的设计),这是最关键的一环。
- 将自身作为一个普通函数来调用,认定它能完成它的工作。
- 调用自身时给的参数不能和自己的完全相同。
- 将一个最简单的情况作为结束条件,放在调用自身之前。
- 检查结束条件是否有疏漏。
三、递归函数的注意点
- 一定要有结束条件,否则会导致死循环
- 能用递归函数实现的需求,就一定可以用循环调用函数来解决,只是代码简洁与性能不同而已
四、递归案例
2.1、1~n的累加和
递归写法
function sum(n) {
//传递进来的是5
//当n==1的时候结束
if (n == 1) {
return 1;
}
//不满足条件的时候,就是当前数字 + 比自己小 1 的数字
return n + sum(n - 1);
}
(sum(5)); // 15
循环写法
function getSum(n) {
var data = 0;
for (var i = 1; i <= n; i++) {
data += i;
}
return data;
}
2.2、求n的阶乘
递归写法
function fn(n) {
// n 就是你要求的终点
if (n === 1) {
// 设置终点位置
return 1;
}
// 当 n 不是 1 的时候
// 就递进去
return n * fn(n - 1);
}
fn(3); // 6
循环写法
function getMul(n) {
var data = 1;
for (var i = 1; i <= n; i++) {
data *= i;
}
return data;
}
2.3、递归求斐波那契数列
斐波那契数列指的是这样一个数列:1 1 2 3 5 8 13 21 34 55 …这个数列从第3项开始,每一项都等于前两项之和
递归写法
function fn(n) {
// n 就是要求的第 n 位
// 设置终点
if (n === 1 || n === 2) {
return 1;
}
// 未到终点
return fn(n - 1) + fn(n - 2);
}
(fn(10)); // 55
循环写法
function getData(n) {
var arr = [1, 1];
for (var i = 2; i < n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
(arr); //[1,1,2,3,5,8,13,21,34,55]
return arr[ - 1];
}
五、经典面试题以及推荐用法
var res = (function (n) {
return n == 1 ? 1 : n * (n - 1);
})(6);
("res" + res); //res720
考察的知识点:
是一个指向正在执行的函数的指针,使用它来代替函数名,可以确保无论怎样调用函数都不会出问题
function res(n) {
return n == 1 ? 1 : n * res(n - 1);
}
var data = res;
res = null;
(data(4));
//res is not a function
由于res变量设置为Null,结果指向原始函数的引用只剩下一个,res已经不是函数,而调用data()会执行res,所以会报错;而使用可以解决这个问题
function res(n) {
return n == 1 ? 1 : n * (n - 1);
}
var data = res;
res = null;
(data(4)); //24
推荐用法
严格模式:使用会报错吗,不过我们可以通过命名函数表达式来达到相同的效果
以下代码创建了一个f()
的命名函数表达式,赋值给res
变量,即使把函数赋值给另一个变量,函数的名字依然有效,递归能正常完成,这种方式在严格模式和非严格模式都能运行
var res = function f(n) {
return n == 1 ? 1 : n * f(n - 1);
};
(res(4)); //24