携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
大家好,我是大帅子,今天给大家讲一下递归吧, let′s go
1. 递归函数是啥
在函数的内部自己调用自己
2. 特点
与循环类似,一般开发中可以用循环解决的,递归也可以解决,就是写法不同而已
3. 单函数递归
自己调用自己
function fn(){
console.log(1)
// 递归调用
fn()
}
fn()
4. 双函数递归
function fn (){
console.log(1)
fn1()
}
function fn1 (){
console.log(8888)
fn ()
}
fn()
5. 一个简单的递归函数
例如我们要求1-5的和
// 用循环求和
let sum = 0
for (let i = 0; i <= 5; i++) {
sum += i
};
console.log(sum);
// 用递归求和
function getSum(num) {
if (num == 1) {
return 1
} else if (num == 2) {
return 2 + getSum(1)
} else if (num == 3) {
return 3 + getSum(2)
} else if (num == 4) {
return 4 + getSum(3)
} else if (num == 5) {
return 5 + getSum(4)
}...
}
console.log(getSum(5));
这个时候肯定有的兄弟们就在想了,这是什么垃圾博主,三行的代码写了30行,别慌铁子们,我们学东西慢慢来嘛,我们可以发现除了上面的num==1
的条件其他的条件似乎都是类似的,那我们就来精简一下
function getSum(num) {
if (num == 1) {
return 1
} else {
return num + getSum(num-1)
}
}
console.log(getSum(5));
打个断点看一下
6.应用场景
在我们实际的开发中,就是用来深拷贝的,实际我们用的递归拷贝并不多,用的多的我就给大家提一下
let obj = {
name: '张三',
age: 18,
hobby: ['唱', '跳', 'rap', '篮球'],
eat: {
name: '北京烤鸭',
drink: '茶颜悦色'
}
}
// 浅拷贝 复制的 对象改变原来的对象一样会跟着改变
let obj1 = obj
obj1.name = 'niu'
console.log(obj, obj1)
//深拷贝
let obj1 = JSON.parse(JSON.stringify(obj))
console.log(obj1 === obj) //false
递归
// 用递归的做法
function diGui(newObj, obj) {
for (let key in obj) {
if (obj[key] instanceof Array) {
// 引用类型 数组
newObj[key] = []
diGui(newObj[key], obj[key])
} else if (obj[key] instanceof Object) {
// 引用类型 对象
newObj[key] = {}
diGui(newObj[key], obj[key])
} else {
//值类型
newObj[key] = obj[key]
}
}
}
let newObj = {}
diGui(newObj, obj)
7. 运用递归获取整个 DOM 树
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<div class="box">
<div>
电子产品
<p>
手机
<b>iPhone</b>
<b>华为</b>
<b>小米</b>
</p>
<p>
笔记本
<b>戴尔</b>
<b>外星人</b>
<b>联想</b>
</p>
</div>
<div>
家具家电
<p>
家具产品
<b>沙发</b>
<b>桌子</b>
<b>椅子</b>
</p>
<p>
家电
<b>冰箱</b>
<b>空调</b>
</p>
</div>
</div>
<script>
function giveMe(arr, ele) {
for (let i = 0; i < ele.children.length; i++) {
// 到现在我们就只能拿到 .box的子代元素
arr.push(ele.children[i])
// 所以我们现在直接调用这个函数就ok了
giveMe(arr, ele.children[i])
}
}
let box = document.querySelector('.box')
let arr = []
giveMe(arr, box)
console.log(arr);
</script>
</body>
</html>
8.递归写三级目录
<!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>
<style>
* {
padding: 0;
margin: 0;
}
.menu p {
width: 100px;
border: 3px solid;
margin: 5px;
}
.menu>div p {
margin-left: 10px;
border-color: red;
}
.menu>div>div p {
margin-left: 20px;
border-color: green;
}
.menu>div>div>div p {
margin-left: 30px;
border-color: yellow;
}
</style>
</head>
<body>
<div class="menu">
<!-- <div>
<p>第一级菜单</p>
<div>
<p>第二级菜单</p>
<div>
<p>第三级菜单</p>
</div>
</div>
</div> -->
</div>
<script>
//服务器返回一个不确定的数据结构,涉及到多重数组嵌套
let arr = [
{
type: '电子产品',
data: [
{
type: '手机',
data: ['iPhone手机', '小米手机', '华为手机']
},
{
type: '平板',
data: ['iPad', '平板小米', '平板华为']
},
{
type: '智能手表',
data: []
}
]
},
{
type: '生活家居',
data: [
{
type: '沙发',
data: ['真皮沙发', '布沙发']
},
{
type: '椅子',
data: ['餐椅', '电脑椅', '办公椅', '休闲椅']
},
{
type: '桌子',
data: ['办公桌']
}
]
},
{
type: '零食',
data: [
{
type: '水果',
data: []
},
{
type: '咖啡',
data: ['雀巢咖啡']
}
]
}
]
function addEle(arr, ele) {
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
// 1. 先创建空元素
let div = document.createElement('div')
// 2. 设置内容
div.innerHTML = `<p> ${arr[i].type || arr[i]} </p>`
// 3. 添加到DOM树
ele.appendChild(div)
// 如果是一级 或者 二级菜单, 则继续递归新增的元素 (如果只有一级二级菜单有data,三级菜单没有data,不需要继续递归了)
if (arr[i].data) {
addEle(arr[i].data, div)
}
};
}
addEle(arr, document.querySelector('.menu'))
</script>
</body>
</html>