• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

深拷贝

武飞扬头像
西门大哥
帮助1

JSON.stringify() 是目前开发过程中最简单的深拷贝方法 其实就是把一个对象序列化成为 JSON 的字符串,并将对象里面的内容转换成字符串,最后再用 JSON.parse() 的方法将 JSON 字符串生成一个新的对象

let q = { age: 1, jobs: { first: 'FE' } } let b = JSON.parse(JSON.stringify(q)) q.jobs.first = 'native' console.log(b.jobs.first)

1 拷贝的对象的值如果有 函数undefinedsymbol 这几种类型,经过 JSON.stringify() 序列后的字符串中这个键值对会消失

2 拷贝 Date引用类型 会变成字符串

3 无法拷贝不可枚举的属性

4 无法拷贝对象的原型链

5 拷贝 RegExp引用类型 会变成空对象

6 对象中含有 NaNInfinity 以及 -Infinity ,JSON.parse()序列化的结果会变成 null

7 无法拷贝对象的循环引用,即 对象成环(obj[key]=obj) 的情况

用递归实现 深拷贝 针对上面几个待解决问题,我们应该怎么做呢?

a. 针对能够遍历对象的不可枚举属性以及 Symbol 类型,我们可以使用 Reflect.ownKeys(可以获取一个对象的所有属性,包括可枚举属性、不可枚举属性和 Symbol 类型属性) 方法 b. 当参数为 Date、Regexp类型,则直接生成一个新的实例返回 c. 利用 Object.getOwnPropertyDescriptors 方法可以获得对象的所有属性,以及对应的特性,顺便结合Object.create 方法创建一个新对象,并继承传入原对象的原型链 d. 利用 weakMap 类型作为 Hash 表,因为 weakMap 是弱引用类型,可以有效防止内存泄露,作为检测循环引用很有帮助,如果存在循环,则引用直接返回 weakmap 存储的值

// 判断一个对象是否为复杂数据类型,即对象或函数类型,且不为 null const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null) // 定义深拷贝函数 deepClone,接受两个参数:obj 为要进行深拷贝的目标对象,hash 为已经拷贝过的对象的哈希表(用于解决循环引用问题) const deepClone = function (obj, hash = new WeakMap()) { // 如果目标对象是日期对象,则直接返回一个新的日期对象,避免修改原日期对象 if (obj.constructor === Date) { return new Date(obj) } // 如果目标对象是正则对象,则直接返回一个新的正则对象,避免修改原正则对象 if (obj.constructor === RegExp){ return new RegExp(obj) } // 如果目标对象已经被拷贝过,则从 hash 中获取已经拷贝过的对象并返回,避免出现循环引用问题 if (hash.has(obj)) { return hash.get(obj) } // 获取目标对象的所有属性描述符 let allDesc = Object.getOwnPropertyDescriptors(obj) // 创建一个新对象 cloneObj,并将其原型链指向 obj 的原型对象 let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc) // 将目标对象和克隆对象的映射关系存入 hash 中,用于解决循环引用问题 hash.set(obj, cloneObj) // 遍历目标对象的所有属性(包括字符串类型和 Symbol 类型的属性名) for (let key of Reflect.ownKeys(obj)) { // 如果目标对象的属性值是复杂数据类型(即对象或数组),则递归调用 deepClone 函数进行深拷贝,并将拷贝结果赋值给克隆对象的对应属性 if (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') { cloneObj[key] = deepClone(obj[key], hash) } else { // 如果目标对象的属性值不是复杂数据类型,则直接将其赋值给克隆对象的对应属性 cloneObj[key] = obj[key] } } // 返回深拷贝后的新对象 return cloneObj }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgahgca
系列文章
更多 icon
同类精品
更多 icon
继续加载