编辑
2023-01-31
前端开发
00

目录

2023-1-27 日,第 623 期 JavaScript Weekly 介绍了最新的原生深拷贝函数 structuredClone(),借此总结一下 JavaScript 中 clone 相关的方法。

JavaScript 中的数据类型分为原始类型和引用类型,他们的区别之一,就是在拷贝时的表现不一样。

  • 原始类型存储在栈内存中,每次拷贝都会生成一份新的数据,对新数据的任何操作都不会影响原有数据。
  • 引用类型存储在堆内存中,拷贝时只会拷贝指向对象的指针,修改新数据会影响原有数据。

浅拷贝 shallow clone

原始类型生成新数据;引用类型生成新的指针,还是指向原有的对象。

Object.assign

js
let user = { name: "John", sizes: { height: 182, width: 50 } } let clone = Object.assign({}, user) alert( user.sizes === clone.sizes ) // true,同一个对象

Spread 语法(对象解构)

js
let user = { name: "John", sizes: { height: 182, width: 50 } } let clone = {...user} alert( user.sizes === clone.sizes ) // true,同一个对象

深拷贝 deep clone

JSON.parse(JSON.stringify())

js
let user = { name: "John", sizes: { height: 182, width: 50 } } let clone = JSON.parse(JSON.stringify(user)) alert( user.sizes === clone.sizes ) // false,不是同一个对象

缺点

  • 无法处理递归数据解构
  • 无法处理部分 JS 内置数据类型:Map, Set, Date, RegExp, ArrayBuffer.
  • 无法拷贝对象的方法
js
const obj = { set: new Set([1, 3, 3]), map: new Map([[1, 2]]), regexp: /foo/, deep: { array: [ new File(someBlobData, 'file.txt') ] }, error: new Error('Hello!') } const clone = JSON.parse(JSON.stringify(obj)) console.log(clone) // 我们会得到 🙂 { set: {}, map: {}, regex: {}, deep: { array: [ {} ] }, error: {}, }

lodash.cloneDeep()

  • 使用 Object.prototype.toString.call 来获取详细类型,不同类型分别处理;
  • 递归克隆,数组遍历项,对象遍历属性;
  • 使用 Array/Map 缓存引用,解决循环引用的问题;
  • loadsh 不会拷贝函数,将返回 {}。 因为克隆函数没有实际意义,公用同一个函数也没问题。 而且涉及到 科里化,this,闭包等问题,无法克隆相等价值的函数。
  • 非要克隆函数的话,可以使用 new Function('return ' + fn.toString())()

缺点

需要额外装包。

structuredClone(结构化克隆)

2022 年,HTML Living Standard 新增了一个全局函数 structuredClone,可以直接深拷贝引用类型。

js
const obj = { title: "Builder.io Conf", date: new Date(123), attendees: ["Steve"] } const clone = structuredClone(obj) console.log(clone) // 我们将得到 😍 { title: "Builder.io Conf", date: "1970-01-01T00:00:00.123Z", attendees: ["Steve"] }

浏览器支持情况(2023 年 1 月 30 日):

缺点

  • 原型链丢失,如果在类实例中使用 structuredClone() ,那么将得到一个普通对象;
  • structuredClone 同样不会克隆函数;
  • 有些值是不能够被结构化的,比如 Error 对象和 DOM 节点,structuredClone 不会克隆这些对象;

参考

本文作者:青波

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!