JavaScript 递归

前端 · 2020-08-15 ·

什么是递归?

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。 简言之:函数内部自己调用自己,这个函数就是递归函数。

递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return。

    var num = 1;
    function fn() {
        console.log("我要抄写10遍,这是抄写的第" + num + "遍");
        if (num == 10) {
            return; // 递归里面必须加退出条件,否则就成了死递归。
        }
        num++;
        fn();
    }
    fn();

1. 利用递归求数学题

1.1 求 1*2*3...*n 阶乘

    function jc(n) {
        if (n == 1) {
            return 1;
        }
        return n * jc(n - 1);
    }
    console.log(jc(3));
    // 加入用户输入的3
    // 第一步求f(3) return 3*f(2)  
    // 第二步求f(2) return 3*(2*f(1))
    // 第三步求f(1) return 3*(2*1)
    // 第四步返回   return 3*2
    // 第五步返回   return 6

1.2 求斐波那契数列 1、1、2、3、5、8、13、21...

    // 1、1、2、3、5、8、13、21...
    // 用户输入一个数字n 就可以求出 这个数字对象的数列值
    // 我们只需要知道用户输入的n前面2项(n-1、n-2)就可以计算出n对象的序列值
    function fbnq(n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fbnq(n - 2) + fbnq(n - 1);
    }
    console.log(fbnq(8));

2 利用递归求:根据id返回对应的数据对象

var data = [{
        id: 1,
        name: "家电",
        goods: [{
            id: 11,
            gname: "冰箱"
        }, {
            id: 12,
            gname: "洗衣机"
        }]
    }, {
        id: 2,
        name: "服饰"
    }];
    // 想要实现输入id号,就可以返回数据对象
    // 1.利用 forEach 去遍历里面的每一个对象
    function getId(json, id) {
        var o = {};
        json.forEach(function(item) {
            //console.log(item); //2个数组元素
            if (item.id == id) {
                //console.log(item);
                o = item;
                return item;
                //2.我们想要得到里层的数据,可以利用递归函数
                //里面应该有goods 这个数组并且数组长度不为0
                //递归退出条件:forEach 里的if、else以及forEach自动调用完结束递归
            } else if (item.goods && item.goods.length > 0) {
                o = getId(item.goods, id);
            }
        });
        return o;
    }
    console.log(getId(data, 12));

3 浅拷贝

浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用

    var obj = {
        id: 1,
        name: "mla",
        info: {
            age: 5
        }
    }
    var o = {};
    for (var key in obj) {
        o[key] = obj[key];
    }
    console.log(o);
    // 这样拷贝属于浅拷贝,只是将obj的info的地址(引用)拷贝到了o.info
    // 如果我修改o、obj中的任何一个,另外一个也将随之改变
    o.info.age = 20;
    console.log(obj);

ES6 提供了浅拷贝的语法糖 Object.assign

    var obj = {
        id: 1,
        name: "mla",
        info: {
            age: 5
        }
    }
    var o = {};
    // ES6 提供了 Object.assign语法糖 实现浅拷贝
    Object.assign(o, obj);
    console.log(o);
    // 这样拷贝属于浅拷贝,只是将obj的info的地址(引用)拷贝到了o.info
    // 如果我修改o、obj中的任何一个,另外一个也将随之改变
    o.info.age = 20;
    console.log(obj);

4 深拷贝

深拷贝拷贝多层,每一级别的数据都会拷贝,对于特殊类型(Array 对象、Object对象...)的数据重新开辟空间

    // 深拷贝拷贝多层,每一级别的数据都会拷贝
    var obj = {
        id: 1,
        name: "mla",
        info: {
            age: 5
        },
        color: ['ping', 'blue']
    }
    var o = {};
    // 封装函数
    function deepCopy(newObj, oldObj) {
        for (var key in oldObj) {
            // 判断我们的属性值属于哪种数据类型
            // 1.获取属性值 oldObj[key]
            var item = oldObj[key];
            // 2.判断这个值是否是数组
            if (item instanceof Array) {
                newObj[key] = [];
                deepCopy(newObj[key], item)
            } else if (item instanceof Object) {
                // 3.判断这个值是否是对象
                newObj[key] = {};
                deepCopy(newObj[key], item)
            } else {
                // 4.属于简单数据类型
                newObj[key] = item;
            }
        }
    }
    deepCopy(o, obj);
    o.info.age = 18;
    console.log(o);
    console.log(obj);
上一篇:
下一篇:
%