如何实现JavaScript手写深拷贝2.0(更新2022-07-15)的完整长尾词?

2026-04-11 05:032阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计676个文字,预计阅读时间需要3分钟。

如何实现JavaScript手写深拷贝2.0(更新2022-07-15)的完整长尾词?

前言+原文+js+深拷贝博客链接,当时写的存在很多不足...现在跟着跟着应用老师复习了下,收获满满。+用+JSON+const b=JSON.parse(JSON.stringify(a))+缺点:+不支持+Date+、+RegExp(正则表达式)+、+函数等。

前言

鄙人老版 js 深拷贝博客链接,当时写的存在很多不足...现在跟着方应杭老师复习了下,收获满满。

用 JSON

const b = JSON.parse(JSON.stringify(a))

缺点:

  1. 不支持 Date、RegExp(正则)、函数等数据;

  2. 不支持引用(即环状结构,类似 window.self = window)。

用递归 基础版

支持 Date、RegExp(正则)、函数等引用数据的拷贝。

const deepClone = (a) => { let res = undefined // 数据类型判断 if (a instanceof Object) { // 类 判断 if (a instanceof Function) { // 箭头函数判断 if (a.prototype) { // 普通函数 res = function (...args) { return a.call(this, ...args) } } else { // 箭头函数 res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) // 日期格式 - 0 自动转换为时间戳 } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 递归 for (let k in a) { if (a.hasOwnProperty(k)) { res[k] = deepClone(a[k]) } } } else { res = a } return res }

测试结果:

完整版(支持引用自身的情况)

比如浏览器的 window.self = window,这个时候如果还用上面的拷贝就会导致无限递归导致栈溢出报错。

正确的做法是添加一个 map 来记录每次拷贝过的数据,如果出现重复的就不再进行拷贝和递归。(ps:为什么用 map?因为对象只能 key 值只能为字符串)

const deepClone = (a, cache) => { let res = undefined if(!cache){ cache = new Map() // 缓存不能全局,最好临时创建并递归传递 } if (a instanceof Object) { // 每次拷贝前判断前面是否已经拷贝过 // 如果出现 a.self = a 在这里就会返回 // 防止后续无限递归导致栈溢出 if (cache.get(a)) { return cache.get(a) } if (a instanceof Function) { if (a.prototype) { res = function (...args) { return a.call(this, ...args) } } else { res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 每次递归前将拷贝的值就存入 map cache.set(a, res) for (let k in a) { if (a.hasOwnProperty(k)) { // 通过参数传递缓存 map res[k] = deepClone(a[k], cache) } } } else { res = a } return res }

测试结果:

如何实现JavaScript手写深拷贝2.0(更新2022-07-15)的完整长尾词?

本文共计676个文字,预计阅读时间需要3分钟。

如何实现JavaScript手写深拷贝2.0(更新2022-07-15)的完整长尾词?

前言+原文+js+深拷贝博客链接,当时写的存在很多不足...现在跟着跟着应用老师复习了下,收获满满。+用+JSON+const b=JSON.parse(JSON.stringify(a))+缺点:+不支持+Date+、+RegExp(正则表达式)+、+函数等。

前言

鄙人老版 js 深拷贝博客链接,当时写的存在很多不足...现在跟着方应杭老师复习了下,收获满满。

用 JSON

const b = JSON.parse(JSON.stringify(a))

缺点:

  1. 不支持 Date、RegExp(正则)、函数等数据;

  2. 不支持引用(即环状结构,类似 window.self = window)。

用递归 基础版

支持 Date、RegExp(正则)、函数等引用数据的拷贝。

const deepClone = (a) => { let res = undefined // 数据类型判断 if (a instanceof Object) { // 类 判断 if (a instanceof Function) { // 箭头函数判断 if (a.prototype) { // 普通函数 res = function (...args) { return a.call(this, ...args) } } else { // 箭头函数 res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) // 日期格式 - 0 自动转换为时间戳 } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 递归 for (let k in a) { if (a.hasOwnProperty(k)) { res[k] = deepClone(a[k]) } } } else { res = a } return res }

测试结果:

完整版(支持引用自身的情况)

比如浏览器的 window.self = window,这个时候如果还用上面的拷贝就会导致无限递归导致栈溢出报错。

正确的做法是添加一个 map 来记录每次拷贝过的数据,如果出现重复的就不再进行拷贝和递归。(ps:为什么用 map?因为对象只能 key 值只能为字符串)

const deepClone = (a, cache) => { let res = undefined if(!cache){ cache = new Map() // 缓存不能全局,最好临时创建并递归传递 } if (a instanceof Object) { // 每次拷贝前判断前面是否已经拷贝过 // 如果出现 a.self = a 在这里就会返回 // 防止后续无限递归导致栈溢出 if (cache.get(a)) { return cache.get(a) } if (a instanceof Function) { if (a.prototype) { res = function (...args) { return a.call(this, ...args) } } else { res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 每次递归前将拷贝的值就存入 map cache.set(a, res) for (let k in a) { if (a.hasOwnProperty(k)) { // 通过参数传递缓存 map res[k] = deepClone(a[k], cache) } } } else { res = a } return res }

测试结果:

如何实现JavaScript手写深拷贝2.0(更新2022-07-15)的完整长尾词?