递归就是函数直接或者是间接的调用自己,相当于循环,使用时必需要有一个跳出条件,否则会进入死循环。它是栈的存取方式,先进后出,后进先出。
主要用于循环,如阶乘函数、幂函数和斐波那契数列。
<script>
function fn(n) {
if (n == 1) {
return n;
}
return fn(n - 1) + n;
}
console.log(fn(5)); //15
</script>
以下为分析过程:
<script>
//分析:
n = 5
function fn(5) {
if (5 === 1) { //不满足
return n;
}
return fn(4) + 5; //10+5=15
}
n = 4
function fn(4) {
if (4 === 1) { //不满足
return n;
}
return fn(3) + 4; //6+4=10
}
n = 3
function fn(3) {
if (3 === 1) { //不满足
return n;
}
return fn(2) + 3; //3+3=6
}
n = 2
function fn(2) {
if (2 === 1) { //不满足
return n;
}
return fn(1) + 2; //1+2=3
}
n = 1
function fn(1) {
if (1 === 1) { //满足
return 1;
}
return fn(1) + 2;
}
</script>
尾递归:尾递归是递归的一种优化,函数的最后一步是调用另一个函数,尾递归函数的每子一层函数不再需要使用父一层的函数执行完毕就会销毁栈记录,避免了内存溢出,节省了内存空间,只走一次,性能很高。
<script>
function fn(n, result) {
return (n === 1) ? result : fn(n - 1, n + result);
}
console.log(fn(5, 1)); //15
</script>
分析过程如下:
<script>
//n=5,result=1;
function fn(5,1) {
return (5 === 1) ? result : fn(4, 6);
}
//n=4,result=6;
function fn(4,6) {
return (4 === 1) ? result : fn(3, 10);
}
//n=3,result=10;
function fn(3,10) {
return (3 === 1) ? result : fn(2, 13);
}
//n=2,result=13;
function fn(2,13) {
return (2 === 1) ? result : fn(1, 15);
}
//n=1,result=15;
function fn(1,15) {
return (1 === 1) ? 15 : fn(1, 15);
}
</script>
递归的运用:深拷贝(deepClone)
浅拷贝在引用类型的时候,它只是复制了地址值,实际上还是指向同一堆内存中的数据而深拷贝则是重新创建了一个相同的数据,二者的堆内存的地址值是不一样的。深拷贝中修改赋值后变量的数据不会对之前的数据产生影响。递归可以用于深拷贝。
<script>
const deepCopy = obj => {
if (typeof obj !== 'object') {
return;
}
const newObj = obj instanceof Array ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
const obj1 = {
a: 10,
b: function () {
console.log(1);
},
c: [1, 2, 3],
d: {
f: [2, { a: 20 }]
},
e: {
h: true
}
};
const obj2 = deepCopy(obj1);
console.log(obj2);
obj2.b = function () {
console.log(2);
};
obj2.b(); //2
obj1.b(); //1
obj2.e = [123];
console.log(obj1.e, obj2.e); //{h: true} [123]
</script>
来源:https://www.cnblogs.com/davina123/p/12175288.html