什么是递归?递归的实现深拷贝。

本文深入探讨了递归的概念,包括其工作原理和构成递归的必要条件。通过一个JavaScript实例,展示了如何使用递归实现对象的深拷贝。此外,还提到了递归在无限循环时可能导致的StackOverflowError问题。文章最后简要介绍了节流和防抖技术在性能优化中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是递归?

递归,就是在运行的过程中自己调用自己。
在这里插入图片描述

构成递归需具备的条件:

  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响, 比如 n 变量
  3. 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
  4. 递归必须向退出递归的条件逼近,否则就是无限递归,出现 StackOverflowError,死龟了:)
  5. 当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕

举个简单的例子,js递归实现对象的深拷贝

定义一个对象

const obj = {
        name:'2323',
        age:15,
        sex:'男',
        friend:[
            {
                name:'lili',
                age:12,
                sex:'女'
            },
            {
                name:'haha',
                age:2,
                sex:'女'
            },
        ]
    }

递归实现函数

 function deepCopy(newObj,oldObj) {  //(新数据,被拷贝数据)
      for(key in oldObj){
      		// 首先判断数据类型是否为数组,因为 ( [1,2] instanceof Object === true)
            if(Array.isArray(oldObj[key])){
                newObj[key] = []
                deepCopy(newObj[key],oldObj[key])
            }else if(oldObj[key] instanceof Object){//如果数据是对象类型
                newObj[key] = {}
                //判断是否是原型链上的属性是则跳出此次循环
				if(!oldObj.hasOwnProperty(oldObj[key])) continue; 
				deepCopy(newObj[key],oldObj[key])
            } else{//数据是基本数据类型
                newObj[key] = oldObj[key]
            }
        }
        return newObj
    }

deepCopy(o,obj )
console.log(o)  //深拷贝完成,并且deepCopy(o,a)的值就是o的值

扩展
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

### 使用递归实现深拷贝的方法 在 JavaScript 中,深拷贝是一种重要的技术手段,尤其适用于复杂的嵌套数据结构。以下是通过递归方法实现深拷贝的关键点以及完整的代码示例。 #### 关键点分析 1. **区分基本类型和引用类型** 在递归过程中,首先要判断当前处理的数据是基本类型还是引用类型。如果是一个基本类型,则直接返回其值;如果是引用类型(如对象或数组),则需要进一步深入递归处理[^5]。 2. **检测循环引用** 如果不注意,递归可能陷入无限循环,尤其是在存在环状引用的情况下。因此,可以通过维护一个已访问对象的集合来避免重复操作同一对象实例[^3]。 3. **分别处理对象和数组** 对于不同的引用类型(如 `Array` 和普通对象 `{}`),应采取适当的方式进行克隆。通常可以利用 `instanceof Array` 或者其他类型的检测工具来进行分支处理。 --- ### 示例代码 以下是一段基于上述原理的手写深拷贝函数: ```javascript function deepClone(obj, visited = new WeakMap()) { // 判断是否为null或者不是object类型 if (obj === null || typeof obj !== 'object') { return obj; } // 检查是否存在循环引用 if (visited.has(obj)) { return visited.get(obj); } // 创建新容器 const cloneObj = Array.isArray(obj) ? [] : {}; // 将当前对象标记为已访问 visited.set(obj, cloneObj); // 遍历并递归复制每一个属性 for (let key in obj) { if (obj.hasOwnProperty(key)) { // 确保只遍历自身的可枚举属性 cloneObj[key] = deepClone(obj[key], visited); // 递归调用 } } return cloneObj; } ``` 此代码实现了以下几个功能: - 支持基础类型和复杂嵌套结构的深拷贝。 - 能够有效防止因循环引用而导致的栈溢出错误。 - 提供了一个简单的接口以便开发者轻松调用该方法。 --- ### 应用场景举例 假设有一个包含多层嵌套的对象如下所示: ```javascript const originalObject = { name: "Alice", hobbies: ["reading", "swimming"], details: { age: 25, address: { city: "New York" } } }; // 进行深拷贝 const clonedObject = deepClone(originalObject); console.log(clonedObject.details.address.city); // 输出:"New York" clonedObject.hobbies.push("coding"); console.log(originalObject.hobbies.length); // 输出:2 (未受影响) console.log(clonedObject.hobbies.length); // 输出:3 (单独修改后的结果) ``` 以上例子展示了原对象与克隆对象之间的独立性,验证了深拷贝的有效性[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值