JavaScript实现深拷贝

// 版本一
function deepclone(target) {
	JSON.parse(JSON.stringify(target));
}
/**
	弊端:
	会忽略undefined, symbol 和函数;
	NaN, Infinity, -Infinity 会被序列化为null;
	不能解决循环引用的问题
*/	
// 版本二
function deepclone(target) {
	let cloneTarget = {} // 定义一个克隆对象

Ï   for (const key in target) { 
      cloneTarget[key] = target[key]
    }
    return cloneTarget
}

/**
	弊端:
	对象并没有实现深拷贝
*/
// 版本三
function deepclone(target) {
	
	// 如果是原始类型,则直接返回
	if (typeof target !== 'object') {
		return target
	}
	// 如果是引用类型,则开始递归
	let cloneTarget = {} // 定义一个克隆对象
Ï   for (const key in target) { 
      cloneTarget[key] = deepclone(target[key])
    }
    return cloneTarget
}

/**
	弊端:
	数组,日期,正则,null没有处理
*/
// 版本四:
function deepclone(target) {
	// 处理null
	if (target === null ) return target;
	// Date
	if (target instanceof Date ) return new Date(target) 
	// Regexp
    if (target instanceof RegExp ) return new RegExp(target) 
	// 如果是原始类型,则直接返回
	if (typeof target !== 'object') {
		return target
	}
	// 如果是引用类型,则开始递归
	// let cloneTarget = {} // 定义一个克隆对象
	 // 定义一个克隆对象 或者 克隆数组 根据原对象生成的
	let cloneTarget = new target.constructor()
Ï   for (const key in target) { 
      cloneTarget[key] = deepclone(target[key])
    }
    return cloneTarget
}

/**
	弊端:
	symbol()
*/
// 版本五
function deepclone(target) {
	// 处理null
	if (target === null ) return target;
	// Date
	if (target instanceof Date ) return new Date(target) 
	// Regexp
    if (target instanceof RegExp ) return new RegExp(target) 
	// 如果是原始类型,则直接返回
	if (typeof target !== 'object') {
		return target
	}
	// 如果是引用类型,则开始递归
	// let cloneTarget = {} // 定义一个克隆对象
	 // 定义一个克隆对象 或者 克隆数组 根据原对象生成的
	let cloneTarget = new target.constructor()
	
	Reflect.ownKeys(target).forEach((key) => {
       cloneTarget[key] = deepclone(target[key])
     })
    return cloneTarget
}
/**
	弊端:
	无法处理循环引用
*/
// 版本六
// 额外开辟一个存储空间来存储当前对象和拷贝对象的对应关系

function deepclone(target, hash = {}) {

      // 开始处理null regexp date
      if (target == null) return target; // null
      // Date
      if (target instanceof Date ) return new Date(target) 
      // Regexp
      if (target instanceof RegExp ) return new RegExp(target) 

      // 如果是原始类型,则无需继续拷贝,直接返回
      if (typeof target !== 'object') return target; // 原始类型

      // 为什么要这么写 不用在拷贝的时候去判断数组类型,
      // 原对象是数组,就创建一个新的克隆数组
      // 原对象是对象,就创建一个新的克隆对象

      if (hash[target]) {
        return hash[target]
      }
      // let cloneTarget = {} // 定义一个克隆对象
      // 创建一个新的克隆数组或者克隆对象
      let cloneTarget = new target.constructor() 
      hash[target] = cloneTarget
      
      // for (const key in target) { 
      //   // 开始递归
      //   cloneTarget[key] = deepclone(target[key])
      // }

      Reflect.ownKeys(target).forEach((key) => {
        cloneTarget[key] = deepclone(target[key], hash)
      })
      return cloneTarget
    }
// 版本七
// 配合垃圾回收机制,防止内存泄漏
function deepclone(target, hash = new WeakMap()) {

      // 开始处理null regexp date
      if (target == null) return target; // null
       // Date
      if (target instanceof Date ) return new Date(target)
      // Regexp
      if (target instanceof RegExp ) return new RegExp(target) 

      // 如果是原始类型,则无需继续拷贝,直接返回
      if (typeof target !== 'object') return target; // 原始类型

      // 为什么要这么写 不用在拷贝的时候去判断数组类型,原对象是数组,就创建一个新的克隆数组
      // 原对象是对象,就创建一个新的克隆对象

      if (hash.get(target)) return hash.get(target)
      // let cloneTarget = {} // 定义一个克隆对象
      // 创建一个新的克隆数组或者克隆对象
      let cloneTarget = new target.constructor() 
      hash.set(target, cloneTarget)

      Reflect.ownKeys(target).forEach((key) => {
        cloneTarget[key] = deepclone(target[key], hash)
      })
      return cloneTarget
    }

写在最后,浏览器其实有自己的深拷贝函数

let obj3 = structuredClone(obj);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值