输出结果如下:

文章插图
当拷贝方法时,也会抛出异常:
const car = {make: 'BMW',move() {console.log('vroom');},};car.basedOn = car;const cloned = structuredClone(car);输出结果如下:
文章插图
DOM 节点当拷贝 DOM 节点时,也会抛出异常:
const input = document.querySelector('#text-field');// ? Failed: HTMLInputElement object could not be cloned.const clone = structuredClone(input);属性描述符、setter 和 getter属性描述符、setter 和 getter 以及类似的元数据都不能被克隆 。例如,对于 getter,结果值被克隆,但 getter 函数本身没有被克隆(或任何其他属性元数据):structuredClone({ get foo() { return 'bar' } })输出结果如下:{ foo: 'bar' }对象原型原型链不能被遍历或拷贝 。所以如果克隆一个实例 MyClass,克隆的对象将不再是这个类的一个实例(但是这个类的所有有效属性都将被拷贝)class MyClass {foo = 'bar'myMethod() { /* ... */ }}const myClass = new MyClass()const cloned = structuredClone(myClass)// { foo: 'bar' }cloned instanceof myClass // false支持拷贝的类型structuredClone() 支持拷贝的类型如下:JS 内置对象Array(数组)、ArrayBuffer(数据缓冲区)、Boolean(布尔类型)、DataView(数据视图)、Date(日期类型)、Error(错误类型,包括下面列出的具体类型)、Map(映射类型)、Object (仅指纯对象,如从对象字面量中创建的对象)、原始类型(除symbol外,即 number、string、null、undefined、boolean、BigInt)、RegExp(正则表达式)、Set(集合类型)、TypedArray(类型化数组) 。
Error 类型Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError 。
Web/API 类型AudioData、Blob、CryptoKey、DOMException、DOMMatrix、DOMMatrixReadOnly、DOMPoint、DomQuad、DomRect、File、FileList、FileSystemDirectoryHandle、FileSystemFileHandle、FileSystemHandle、ImageBitmap、ImageData、RTCCertificate、VideoFrame 。
浏览器支持目前主流浏览器都支持 structuredClone API:

文章插图

文章插图
为什么不用 JSON.parse(JSON.stringify(x))?我们平时可能会通过 JSON.parse(JSON.stringify(x)) 来进行深拷贝,那它有什么缺点呢?
来看下面的例子:
const originalObject = {title: "hello",date: new Date(123),attendees: ["Steve"]}const copied = JSON.parse(JSON.stringify(originalObject))通过这种方式,得到的 copied 值如下:{title: "hello",date: "1970-01-01T00:00:00.123Z",attendees: ["Steve"]}可以看到,这里的 date 并不是我们想要的 Date 对象,而是一个字符串 。发生这种情况就是因为 JSON.stringify 只能处理基本对象、数组和基本类型,而其他类型的值在转换之后都可能出现出乎意料的结果,例如 Date 会转化为字符串,Set 会转化为 {} 。JSON.stringify甚至完全忽略某些内容,比如undefined或函数 。例如:
const originalObject = {set: new Set([1, 3, 3]),map: new Map([[1, 2]]),regex: /foo/,deep: { array: [ new File(someBlobData, 'file.txt') ] },error: new Error('Hello!')}const copied = JSON.parse(JSON.stringify(originalObject))这里得到的 copied 值如下:{set: {},map: {},regex: {},deep": {array: [{}]},error: {},}除此之外,JSON.parse(JSON.stringify(x)) 无法对包含循环引用的对象进行深克隆:const originalObject = {set: new Set([1, 3, 3]),map: new Map([[1, 2]]),regex: /foo/,error: new Error('Hello!')}originalObject.circular = originalObjectconst copied = JSON.parse(JSON.stringify(originalObject))当执行上述代码时,就会报错:
文章插图
所以,如果对象没有上面说的这些情况,使用 JSON.parse(JSON.stringify(x)) 进行深克隆是完全没有问题的 。如果有,就可以使用 structuredClone() 来进行深拷贝 。
最后大家明白看完这篇文章深入剖析JavaScript中深浅拷贝,理解多少了,欢迎在评论区讨论 。
推荐阅读
- 5个等级的数据分析,哪个最深入?
- 最流行的 WebAssembly 语言,会是 JavaScript 吗?
- 人际关系|深入解析职场沟通:概念、类型和重要性
- |男性管理者职场历程剖析:担任正科15年还有机会晋升副处级吗?
- 2023年,Rust能干掉JavaScript吗?
- JS混淆加密应用场景有哪些?
- JavaScript日期处理不再难!Day.js带你飞!
- 饵料|有效解决杂鱼闹窝的方法剖析!敢于诱鱼,善于总结你就是高手!
- 深入探究Java IO流:基础知识、流类型及使用方法
- 深入理解Java中hashCode的作用
