核心实现思路是递归
先上代码
function deepClone(obj) { //第一行 声明函数
if (typeof obj !== 'object' || obj == null)return obj // 第二行 非对像和null无需遍历
let result = Array.isArray(obj) ? [] : {} //第三行 定义对象要返回的数据结构 数组为[] 对象为{}
for (let i in obj) { //第四行 开始遍历
result[i] = deepClone(obj[i]) //第五行 函数自己调用自己(递归)实现深拷贝
} //第六行 右花括号包裹循环体语句
return result //第七行 返回深拷贝对象
} //第八行 右花括号 包裹函数体语句
最后我们再来复习一下递归:
什么是递归?(What)
官方解释:
函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代。在新的迭代中,又会执行调用函数自身的语句,从而又产生一次迭代。当函数执行到某一次时,不再进行新的迭代,函数被一层一层返回,函数被递归。
我的白话理解:递归就是在函数体内自己调用自己。
为什么要使用递归?(Why)
因为递归可以把一些大型的复杂的问题转化为很多层原理相似的小问题,重点是(原理相似)。
举个栗子,计算数字n的阶乘,计算公式是:1**2*3*4……n*
利用递归的思想(把复杂问题具象为若干个原理相似的小问题),把上述计算公式抽离成很多个n*(n-1)即可(因程序需要结束,就要有临界值,所以我们倒过来,从n开始乘,直到n等于1结束)。
这样一来,计算数字n阶乘的代码实现就呼之欲出啦:
function jieCheng(n){
return n === 1? 1: n * jieCheng(n-1) //这里的n==1是递归实现的条件之一,即递归出口,后面有提到
}
//验证
console.log(jieCheng(6)) // 720
如何实现递归?(How)
实现递归有2个要素
要素1:递归出口
也就是递归的结束条件,如果没有这个条件,你的程序永远不会结束,会变成死循环。所以一定要注意。
如上述阶乘计算的离子中,递归出口是n === 1这个条件及其返回值
要素2:递归体:也就是你从大问题抽离或分解出来的一个个原理相似的小问题
如上述阶乘计算的离子中,递归体就是n * jieCheng(n-1)