浅谈递归

242 阅读2分钟

1.什么是递归函数:在函数内部调用自己

2.递归函数的特点:

  • 一般能用循环实现的,也可以用递归实现
  • 递归也要有结束条件,否则会导致死循环

3.递归的简单实现

单函数递归:自己调用自己

//死循环,慎用!
function fn() {
    console.log('1111')
    fn()
}
fn()

image.png

双函数递归:两个函数互相调用

function fn1() {
    console.log('6666')
    fn2()
}

function fn2() {
    console.log('8888')
    fn1()
}

fn1()

image.png

4.递归求累加和

4.1回顾 for 循环求累加和

//◆求1-100的累加和,复用性低
let sum = 0
for (let i = 1; i <= 100; i++) {
    sum += i
}
console.log(sum)//5050
//◆把求累加和封装成函数,复用性高
function getSum(min, max) {
    let sum = 0
    for (let i = min; i <= max; i++) {
        sum += i
    }
    return sum
}
console.log(getSum(1, 100))//5050
console.log(getSum(50, 200))//18875

4.2实现递归求累加和

//◆求1-5的累加和,看看内部如何递归?
function getSum(n) {
    if (n == 1) {
        return 1
    } else if (n == 2) {
        return 2 + getSum(1)
    } else if (n == 3) {
        return 3 + getSum(2)
    } else if (n == 4) {
        return 4 + getSum(3)
    } else if (n == 5) {
        return 5 + getSum(4)
    }
}
console.log(getSum(5))//15
//◆递归求1-n的累加和(代码优化)
function getSum(n) {
    return n == 1 ? 1 : n + getSum(n - 1)
}
console.log(getSum(5))//15
console.log(getSum(10))//55
console.log(getSum(100))//5050
//◆递归求min-max的累加和(提高复用性)
function getSum(min, max) {
    let sum = 0
    if (max >= min) {
        sum += max + getSum(min, max - 1)
    }
    return sum
}
console.log(getSum(1, 10))//55
console.log(getSum(1, 100))//5050
console.log(getSum(100, 200))//150150

5.递归使用场景:深拷贝

5.1回顾浅拷贝

浅拷贝 : 拷贝的是栈中的地址,修改拷贝后的数据,原数据会改变

let obj = {
    name: '张三',
    age: 18,
    hobby: ['吃饭', '睡觉', '敲代码'],
    job: function () {
        console.log('程序员')
    }
}
let obj1=obj
console.log(obj1 === obj)//true
obj1.name = '李四'
console.log(obj1 === obj)//true

5.2递归实现深拷贝

深拷贝 : 拷贝的是堆中的数据,修改拷贝后的数据,对原数据没有影响

  • forin 遍历原对象中的每一个成员,赋值给新的对象
  • instanceof 检测对象内部数据类型
    • 如果遇到属性值是数组,继续递归拷贝数组内部数据
    • 如果遇到属性值是对象,继续递归拷贝对象内部数据
    • 如果遇到属性值是值类型,直接赋值即可
  • 声明一个新对象存储拷贝后的数据,开始拷贝
let obj = {
    name: '张一一',
    age: 40,
    hobby: ['吃饭', '睡觉', '敲代码'],
    children: {
        son: {
            name: '张小样',
            age: 18
        },
        daughter: {
            name: '张小美',
            age: 16
        }
    }
}

function deepClone(newObj, obj) {
    for (let key in obj) {
        if (obj[key] instanceof Array) {
            newObj[key] = []
            deepClone(newObj[key], obj[key])
        } else if (obj[key] instanceof Object) {
            newObj[key] = {}
            deepClone(newObj[key], obj[key])
        } else {
            newObj[key] = obj[key]
        }
    }
}

let newObj = {}
deepClone(newObj, obj)
console.log(newObj === obj)//false
newObj.age = 39
console.log(obj.age)//40

5.3深拷贝的其它方式(补充)

只需要把js对象先转成json,然后转成js。 就可以实现深拷贝

let obj = {
    name: '张三',
    age: 18,
    hobby: ['吃饭', '睡觉', '敲代码'],
}
let obj3= JSON.parse(JSON.stringify(obj))
console.log(obj3=== obj)//false
obj3.name = '李四'
console.log(obj.name)//张三