递归 从入门到入土

140 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

  • 1.递归函数:一个函数自己调用自己

  • 2.递归函数特点

    • a.一定要有结束条件,否则会导致死循环
    • b.能用递归函数实现的需求,就一定可以用循环调用函数来解决,只是代码简洁与性能不同而已
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
        1. 递归函数 : 在函数中自己调用自己

        2. 递归特点
            a. 能用递归实现的功能一定可以用循环,只是语法不同
            b. 递归一定要有结束的条件,否则会导致死循环
         */

        //一个函数递归
        // function fn(){
        //     console.log('哈哈');
        //     fn();
            
        // };

        // fn();

        //两个函数递归
        // function fn1(){
        //     console.log('哈哈');
        //     fn2();
            
        // };

        // function fn2(){
        //     console.log('呵呵');
        //     fn1();
            
        // };
        // fn2();


        //需求:写一个函数,打印三次 班长爱坤哥

        let i = 1;
        function fn(){
            console.log('班长爱坤哥');
            i++;
            if(i <= 3){
                fn();
            };
            
            //循环实现
            // for(let i = 1;i<=3;i++){
            //     console.log('班长爱坤哥');
                
            // };
        };

        fn();
    </script>
</body>
</html>

1.2-递归应用场景:浅拷贝与深拷贝

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /*浅拷贝与深拷贝概念主要针对于对象这种数据类型 
        
        1.浅拷贝: 拷贝的是地址
            * 特点:修改拷贝后的数据,原数据也会随之修改
        2.深拷贝:拷贝的是数据
            * 特点:修改拷贝后的数据,对原数据没有影响
         */

      let obj = {
        name: 'Superman',
        age: 32,
        hobby: ['上班', '敲代码', '前端程序员'],
        class: {
          name: '我是超人',
          salary: [18888, 12000, 10000]
        }
      }

      //1.浅拷贝: 拷贝的是地址
      let obj1 = obj
      obj1.name = '李宗盛'
      console.log(obj, obj1)

      //2.深拷贝:拷贝的是数据
      //核心原理:使用递归。 只要遇到属性值是引用类型,则遍历。

      function kaobei (newObj, obj) {
        // 遍历
        for (let key in obj) {
          if (obj[key] instanceof Array) {
            // obj[key] 是数组
            // obj[key]是数组
            newObj[key] = []

            kaobei(newObj[key], obj[key])
          } else if (obj[key] instanceof Object) {
            // obj[key] 是对象
            // obj[key]再遍历拷贝
            newObj[key] = {}

            kaobei(newObj[key], obj[key])
          } else {
            newObj[key] = obj[key]
          }
        }
      }

      let obj2 = {}
      //深拷贝
      kaobei(obj2, obj)
      //修改拷贝后的数据
      obj2.name = '颜值担当'
      obj2.hobby = '唱歌'
      console.log(obj,obj2)
    </script>
  </body>
</html>

1.3-递归应用场景:扁平数据结构转成树

image.png

我们列表型数据的关键属性: id 和 pid, id指的是自己的部门id, pid指的是父级部门的id (空则没有父级部门)

然后,我们需要将列表型的数据,转化成树形数据,这里需要用到 递归算法

/**
 * 将列表型的数据转换成树形数据 => 递归算法
 * 这里是要建立树形结构, 所以一定要找一个头
 */
export function tranListToTreeData(list, rootValue) {
  const arr = []
  list.forEach(item => {
    if (item.pid === rootValue) {
      // 以 item.id 作为 父 id, 接着往下找
      const children = tranListToTreeData(list, item.id)
      if (children.length > 0) {
        item.children = children
      }
      // 将item项, 追加到arr数组中
      arr.push(item)
    }
  })
  return arr
}

这样 数组arr中就是我们想要的树形结构的数据了 三级结构就一次类推