JavaScript 手写实现深克隆

本文探讨前端面试中常见的基础知识点——深克隆。通过提供的JavaScript代码示例,详细解释如何实现深克隆,包括处理日期、正则等特殊对象,并利用WeakMap解决循环引用问题。对于前端开发者来说,掌握深克隆是提升技能的重要一环。

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

前言:

深克隆是前端面试的一个非常基础的知识点,一般要求大家能手写出来,现在分享给大家一下本人自己写的深克隆代码,希望对大家有所帮助!

代码:

 

const isComplexDataType = obj=> (typeof obj === 'object' && obj !== null);

function deepClone(obj,hash = new WeakMap()){
	if(obj.constructor === Date){
    return new Date(obj)       // 日期对象直接返回一个新的日期对象
  }
  if(obj.constructor === RegExp){
  	return new RegExp(obj)     //正则对象直接返回一个新的正则对象
  }
  // 如果循环引用了就用 weakMap 来解决
  if(hash.has(obj)){
  	return hash.get(obj);
  }
  let allDesc = Object.getOwnPropertyDescriptors(obj);
  // 遍历传入参数所有键特性
  let cloneObj = Object.create(Object.getPrototypeOf(obj),allDesc);
  
  hash.set(obj,cloneObj);
  
  for(let key of Reflect.ownKeys(obj)){
  	cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
  }
  return cloneObj
}

### 使用递归实现深拷贝的方法 在 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
发出的红包

打赏作者

靖凡无所畏惧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值