JS 递归时候犯得一个错误

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37701381/article/details/81395557

JS 递归时候犯得一个错误

有三层的树状JSON数据,想要用递归的方式取出第三层的数据,很简单的一个实现,函数调函数,但是在判断的时候做了一个错误,那就是递归中的if判断

先看数据

var data = '[\n' +
            '  \n' +
            '  {\n' +
            '    "name": "部件管理",\n' +
            '    "id": "9901e0fbb6e04189b758f699be2c3d72",\n' +
            '    "pId": "0",\n' +
            '    "parentspath": "/xxx/xxx",\n' +
            '    "checked": true,\n' +
            '    "children": [\n' +
            '      {\n' +
            '        "name": "部件管理",\n' +
            '        "id": "9f73f59b937d449bb0130083b0325e0f",\n' +
            '        "pId": "9901e0fbb6e04189b758f699be2c3d72",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "34984832192e4f428b57c53419f6e37f",\n' +
            '        "moduleId": "d3c59c119c5b4ee0b8c89f0cefd30a39",\n' +
            '        "funcUrl": "/tpl/info-management/basic-data/component/component-manage.html",\n' +
            '        "icon": "fa fa-cogs",\n' +
            '        "requireJS": [\n' +
            '          "/js/controllers/info-management/basic-data/component/component-manage.js",\n' +
            '          "/css/info-management.css"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "57",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "数据导入",\n' +
            '        "id": "24c332faea51458aa3674d18652c6065",\n' +
            '        "pId": "9901e0fbb6e04189b758f699be2c3d72",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "390b8f2939eb4fe3a37d8488de02768e",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/data-import/dataImport.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/data-import/dataImport.js",\n' +
            '          "vendor/fileinput/fileinput.min.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "537",\n' +
            '        "menuType": null\n' +
            '      }\n' +
            '    ],\n' +
            '    "type": "1",\n' +
            '    "functionId": null,\n' +
            '    "moduleId": null,\n' +
            '    "funcUrl": null,\n' +
            '    "icon": "fa fa-cog",\n' +
            '    "requireJS": [],\n' +
            '    "opertateType": null,\n' +
            '    "seqId": null,\n' +
            '    "menuType": null\n' +
            '  },\n' +
            '  {\n' +
            '    "name": "信息管理",\n' +
            '    "id": "1e50e92fb3e7495e96b137b474fee07a",\n' +
            '    "pId": "0",\n' +
            '    "parentspath": "/xxx/xxx",\n' +
            '    "checked": true,\n' +
            '    "children": [\n' +
            '      {\n' +
            '        "name": "数据字典管理",\n' +
            '        "id": "5391013084db4e848f87dbb50a6742ac",\n' +
            '        "pId": "1e50e92fb3e7495e96b137b474fee07a",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "019db89af28a4a1190c57958379a0c4c",\n' +
            '        "moduleId": "4e65d687e7344541bf69a5bd59349065",\n' +
            '        "funcUrl": "tpl/dataDictionary-management/dataDictionary-management.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/dataDictionary-management/dataDictionary-management.js",\n' +
            '          "/js/globaltree.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "53",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "部门管理",\n' +
            '        "id": "62fb372667bf4e9688bcacdbc5d1bbff",\n' +
            '        "pId": "1e50e92fb3e7495e96b137b474fee07a",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "a7117da3fdba4c3eba4e3f6382437f4c",\n' +
            '        "moduleId": "4e65d687e7344541bf69a5bd59349065",\n' +
            '        "funcUrl": "tpl/department-management/department-management.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/department-management/department-management.js",\n' +
            '          "/js/globaltree.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "594",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "行政区域管理",\n' +
            '        "id": "b7fd002465e14ac9a70162c3b8d945ee",\n' +
            '        "pId": "1e50e92fb3e7495e96b137b474fee07a",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "967a5137702d4b699776aac8fad8b6a4",\n' +
            '        "moduleId": "4e65d687e7344541bf69a5bd59349065",\n' +
            '        "funcUrl": "tpl/region-management/region-manage.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/region-management/region-manage.js",\n' +
            '          "/js/globaltree.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "52",\n' +
            '        "menuType": null\n' +
            '      }\n' +
            '    ],\n' +
            '    "type": "1",\n' +
            '    "functionId": null,\n' +
            '    "moduleId": null,\n' +
            '    "funcUrl": null,\n' +
            '    "icon": "fa fa-book",\n' +
            '    "requireJS": [],\n' +
            '    "opertateType": null,\n' +
            '    "seqId": null,\n' +
            '    "menuType": null\n' +
            '  },\n' +
            '  {\n' +
            '    "name": "本地测试",\n' +
            '    "id": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '    "pId": "0",\n' +
            '    "parentspath": "/xxx/xxx",\n' +
            '    "checked": true,\n' +
            '    "children": [\n' +
            '      {\n' +
            '        "name": "模板数据",\n' +
            '        "id": "24768d1bbaff49c290493d32eeec0140",\n' +
            '        "pId": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "5dcc804a33d24bd9837ba9b357530b9d",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/data-template/template.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/data-template/template.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "534",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "数据库源",\n' +
            '        "id": "12c74e7f2336446f93cca537b0bcf867",\n' +
            '        "pId": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "30411f81dab444fd978b2fc4626b76e5",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/db-source/dbsource.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/db-source/dbsource.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "535",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "数据导入",\n' +
            '        "id": "54315399fb784b09be71fbcf0acad039",\n' +
            '        "pId": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "390b8f2939eb4fe3a37d8488de02768e",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/data-import/dataImport.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/data-import/dataImport.js",\n' +
            '          "vendor/fileinput/fileinput.min.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "537",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "导入日志",\n' +
            '        "id": "94a0f468b19c4d3d9d16058ce25078f4",\n' +
            '        "pId": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "3cd69d1797294efabfecdb64c9e170e3",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/data-log/dataLog.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/data-log/dataLog.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "538",\n' +
            '        "menuType": null\n' +
            '      },\n' +
            '      {\n' +
            '        "name": "模板工具",\n' +
            '        "id": "243f7f9765b3499ea0549bd985cdfc0d",\n' +
            '        "pId": "59d6004cbba74f45b6543f8c6afd35e8",\n' +
            '        "parentspath": "/xxx/xxx",\n' +
            '        "checked": true,\n' +
            '        "children": null,\n' +
            '        "type": "1",\n' +
            '        "functionId": "1ccf6c64c9e84d089924feb358c7a729",\n' +
            '        "moduleId": "d5943a9f2cf74ec9971f19b0e9d24b7a",\n' +
            '        "funcUrl": "tpl/data/data-export/field-tool/field-tool.html",\n' +
            '        "icon": null,\n' +
            '        "requireJS": [\n' +
            '          "js/controllers/data/data-export/field-tool/field-tool.js"\n' +
            '        ],\n' +
            '        "opertateType": null,\n' +
            '        "seqId": "536",\n' +
            '        "menuType": null\n' +
            '      }\n' +
            '    ],\n' +
            '    "type": "1",\n' +
            '    "functionId": null,\n' +
            '    "moduleId": null,\n' +
            '    "funcUrl": null,\n' +
            '    "icon": null,\n' +
            '    "requireJS": [],\n' +
            '    "opertateType": null,\n' +
            '    "seqId": null,\n' +
            '    "menuType": null\n' +
            '  }\n' +
            ']';

这是一个模拟数据,模拟一个系统中需要菜单列表时候的场景,分为是一级、二级和三级菜单的树状

看递归

var moduleList = JSON.parse(data);
        //拷贝对象方法
        function copy(obj){
            var newobj = {};
            for ( var attr in obj) {
                newobj[attr] = obj[attr];
            }
            return newobj;
        };
        console.log(moduleList);
        var obj = [];
        var moduleTree = function(moduleList, moduleId, seqId, parentNode){
            if (!moduleList){
                return;
            }
            for(var i = 0; i < moduleList.length; i++){
                if (moduleList[i].children != null){
                    moduleTree(moduleList[i].children, moduleId, seqId, moduleList[i]);
                    if (moduleId === moduleList[i].moduleId && seqId === moduleList[i].seqId){
                        var node = copy(moduleList[i]);
                        node.name = parentNode.name === null ? '' : parentNode.name + "—" + node.name;
                        obj.push(node);
                    }
                }

            }
        };
        $scope.text1 = function () {
            moduleTree(moduleList,"d5943a9f2cf74ec9971f19b0e9d24b7a","537",null);
            console.log(obj);
            $scope.modules = obj;
        }

是不是看似没毛病?稳如老狗?错了。。。我当时也是这么天真的认为,我的代码完美,没毛病。。。

但是,血崩!!!在循环里第一个if里判断有没有子级的时候,我们只进行一个递归操作,这个时候又加上一层if循环,而在text1这个方法里,我们是将指定参数放进去做判断的;而这个时候,第一次进来,发现有子级,进来第一个判断,再进行第二次判断,发现条件不匹配,第二次进来,也发现有子级,进来第一个判断,又进行第二个判断,还是条件不匹配,重点来了,只有三层数据,到第三次进来的时候,已经没有子级了,第一个判断条件进不去,导致了我们条件匹配的第二个判断做不了,也就赋值不了,所以我拿的一直是空数组

修改后的代码

 for(var i = 0; i < moduleList.length; i++){
                if (moduleList[i].children != null){
                    moduleTree(moduleList[i].children, moduleId, seqId, moduleList[i]);
                }
                if (moduleId === moduleList[i].moduleId && seqId === moduleList[i].seqId){
                    var node = copy(moduleList[i]);
                    node.name = parentNode.name === null ? '' : parentNode.name + "—" + node.name;
                    obj.push(node);
                }

            }

正确的做法是将第二个判断取出,与第一次判断并行,这样才是正确的逻辑:第一次循环,有子级,递归,第二次循环,有子级,递归,第三次没有子级,不走第一个判断,走第二个判断,没错,这个时候就拿到了最后一级的匹配数组

其他

用了一个JS复制对象的方法,因为每次循环给node赋值的时候,之前取出来的moduleList也会被改变,因为指针是同一个,利用复制对象的方法,让moduleList值不改变

猜你喜欢

转载自blog.csdn.net/m0_37701381/article/details/81395557
今日推荐