JavaScript 递归的几种写法
Posted 笑虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 递归的几种写法相关的知识,希望对你有一定的参考价值。
文章目录
匿名函数实现递归
知识点 arguments.callee
对于arguments
大家应该都认识吧。callee
就是函数自身
官方建议用命名函数
实现递归。(也就是叫你调用函数名)
[
id: 1,
children: [...]
,
id: 2,
children: [...]
]
// 把一个树展平。
function recursion(arr)
var flatObj = ;
(function(arr)
for(var i=0,len=arr.length; i<len; i++)
var item = arr[i];
if(item.children)
flatObj[item.id] = item.children;
arguments.callee(item.children)
// 其它逻辑代码
)(arr);
return flatObj;
具名函数递归
递归调用接口,结果组装成 map
function recursionFun(param)
var arr = [];
fetch('https://blog.csdn.net/jx520/getMenu?pid='+param)
.then(response =>response.json())
.then(jsonArray =>
var textArr = [];
jsonArray.forEach(function (item, index, jsonArr)
if(item.isFolder)
arr.push([[item.title] , recursionFun(item.key)]); // 有子级,递归调用
else
textArr.push(item.title); // 叶结点内容先压进数组,下面会转成字符串
);
// 有内容就压入,没有内容就跳过。
textArr.length && arr.push(textArr.join(','));
);
return arr;
var json = recursionFun(0); // 从根节点开始
// 等异步返回结果再执行才看的到效果。
JSON.stringify(json,null,4);
格式化数据
var path = [];
var arr = [];
function recursionFun(list)
list.forEach( (v, i) =>
if(typeof v === "string")
arr.push(path.join('-') + " : " + v);
else
path.push(v[0]);
recursionFun(v[1]);
path.pop();
);
recursionFun(json[0][1]);
arr.join('\\n');
遍历树形结构生成SQL
tree 结构生成 sql
树型结构生成sql,用于插入mysql
var sql = [];
var tree = [
"id":1,"pid":0,"name":"a", "id":2,"pid":1,"name":"a1",
"id":3,"pid":1,"name":"a2", "id":4,"pid":3,"name":"a201",
"id":5,"pid":3,"name":"a202", "id":6,"pid":4,"name":"a20101"
];
var table = "chn"; // 表名
var fields = "pid, name"; // 字段名:父id、名称
var id = "id"; // tree对象id
var pid = "pid"; // tree对象父id
var value = "name"; // tree对象value
function recursionFun(tree)
tree.forEach( (obj) =>
var parentId = obj[pid]== 0 ? 0 : `@parentId$obj[pid]`;// 第一级pid为0
sql.push(`INSERT INTO $table ($fields) VALUES ($parentId,'$obj[value]');`);
sql.push(`SELECT @parentId$obj[id] := LAST_INSERT_ID();`)
);
tree.forEach( (obj) =>
if(obj.children && obj.children.length)
recursionFun(obj.children);
);
recursionFun(tree);
sql.join("\\n");
直接遍历dom树生成SQL
展开树1次
document.querySelectorAll("#divXXX img[src='/img/1.gif']").forEach(e=>
e.onclick();
);
var sql = [];
var table = "chn"; // 表名
var fields = "pid, name"; // 字段名:父id、名称
function rec(eleId, parentId)
parentId = (parentId == 0 || parentId) ? parentId : "@parentId"+eleId;
eleId = eleId[0] == "#" ? eleId : "#"+eleId;
document.querySelectorAll(eleId+'>div:not([id$="chl"])').forEach(ele =>
var input = ele.querySelector('input[type="hidden"]');
sql.push(`INSERT INTO $table ($fields) VALUES ($parentId,'$input.value');`);
sql.push(`SELECT @parentId$ele.idchl := LAST_INSERT_ID();`)
);
document.querySelectorAll(eleId+'>div[id$="chl"]').forEach(ele =>
if(ele.childElementCount)
rec(ele.id);
);
rec("#父id", 0);
sql.join("\\n");
给树补 id、pid
有的时候,我们拿到一个树,但是没有id
、pid
。
var tree = [
"name":"a", "children":["name":"aa", "children":["name":"aaa1","name":"aaa2"],],
"name":"b", "children":["name":"bb", "children":["name":"bbb1","name":"bbb2"],],
"name":"c", "children":["name":"cc", "children":["name":"ccc1","name":"ccc2"],],
"name":"d", "children":["name":"cc", "children":["name":"ddd1","name":"ddd2"],]
];
我们如下处理给它补上。
var pids = [0];
var i = 1;
function recursionFun(tree)
var pid = pids.pop();
tree.map( (item) =>
Object.assign(item, "id": i++ , "pid":pid);
return item;
);
tree.forEach( (item) =>
var children = item.children;
if(children && children.length)
pids.push(item.id)
recursionFun(children);
);
recursionFun(tree);
如果叶子节点直接是字符串
var tree = [
"name":"a", "children":["name":"aa", "children":["aaa1","aaa2"]],
"name":"b", "children":["name":"bb", "children":["bbb1","bbb2"]],
"name":"c", "children":["name":"cc", "children":["ccc1","ccc2"]],
"name":"d", "children":["name":"cc", "children":["ddd1","ddd2"]]
];
var pids = [0];
var i = 1;
function recursionFun(list)
var pid = pids.pop();
list.map( (item,index,arr) =>
if(typeof item === "string")
arr[index] = "id": i++ , "pid":pid, name: item;
else
Object.assign(item, "id": i++ , "pid":pid);
return item;
);
list.forEach( (item) =>
var children = item.children;
if(children && children.length)
pids.push(item.id)
recursionFun(children);
);
recursionFun(obj);
console.table(obj)
递归处理对象的键值对
将键值对的处理逻辑提取出来,增加灵活性。
如果值是对象,则调用 key 处理器时,还给了类型标识 isObj = true
。
/**
* 递归处理所有键值对
* @param obj 待处理的对象
* @param processKey 处理key的方法
* @param processValue 处理value的方法
*/
function recursionProcessObject(obj, processKey = (k, isObj)=>k, processValue = (v)=>v)
function recursionFn(targetObj)
// 如果是数组,对每个元素调用递归处理函数
if (Array.isArray(targetObj))
return targetObj.map(v => recursionFn(v));
// 否则:累加处理键值对。
return Object.entries(targetObj).reduce((resultObj, [currentKey, currentValue]) =>
// 如果是对象: 处理key并递归解析象
if (typeof currentValue === "object")
return ...resultObj, [processKey(currentKey, true)]: recursionFn(currentValue) ;
// 使用给定的 lambda 分别处理键值对。
return ...resultObj, [processKey(currentKey)]: processValue(currentValue) ;
, ); // 累加器初始为
// 调用递归函数处理对象
return recursionFn(obj);
test
var obj = "a": "b": "c": "d": 4;
var result = recursionProcessObject(obj, k => `【$k】`, v => v*2);
console.log(JSON.stringify(result, null, 4));
"【a】":
"【b】":
"【c】":
"【d】": 8
以上是关于JavaScript 递归的几种写法的主要内容,如果未能解决你的问题,请参考以下文章