JavaScript中structuredClone()新特性:一行代码达成高效深拷贝

JavaScript中structuredClone()新特性:一行代码实现高效深拷贝

目录

JavaScript新特性structuredClone():一行代码优化深拷贝策略

一、structuredClone()相关介绍

1、structuredClone()的定义

structuredClone()是浏览器与Node.js原生提供的API,其底层运用更高效的C++实现方式,相较于JS层面的JSON.stringify/parse组合,性能往往更为出色。当面对结构复杂或嵌套层级较多的情况时,差异会更加明显,它无需先转换成字符串再进行解析,避免了冗余的编码与解码过程。

2、structuredClone()的环境支持情况

该API在Node.js 17及以上版本、Chrome 98及以上版本、Firefox 94及以上版本中能够得到支持。

3、structuredClone()无法克隆的内容

下面列出了不支持或无法克隆的类型及结构情况:

不支持或无法克隆的类型/结构 具体说明
函数(Function 函数或者方法无法被克隆
Symbol Symbol属性会被忽略
类实例的方法/原型链 原型链不会被保留,克隆后的对象并非原类的实例
DOM节点(如Element、Node) 不支持DOM对象,例如浏览器中的HTML元素
Proxy对象 代理对象(Proxy)无法被克隆
WeakMap / WeakSet 由于其不可枚举以及弱引用的特性,无法被克隆
函数作用域内的闭包变量 本质上函数无法被克隆,所以闭包变量也无法保留
不可序列化的host对象 比如浏览器特有的某些对象,像Window, FileList

4、基础应用案例

structuredClone()能够支持Map、Set、Blob、Date、File等JSON.parse(JSON.stringify(obj))不支持的类型,示例如下:

const original = {
    // 原始类型
    string: 'Hello',
    number: 123,
    boolean: true,
    null: null,
    undefined: undefined, // JSON会丢失,structuredClone保留

    // 日期对象(JSON会转为字符串,structuredClone保持为Date对象)
    date: new Date('2023-06-15'),

    // 正则表达式(JSON会转为空对象,structuredClone保持为RegExp对象)
    regex: /pattern/g,

    // 集合类型
    map: new Map([['key', 'value']]),
    set: new Set([1, 2, 3]),

    // 二进制数据
    arrayBuffer: new Uint8Array([1, 2, 3]).buffer,
    typedArray: new Uint8Array([1, 2, 3]),

    // 嵌套数组和对象
    array: [1, 2, { nested: true }],
    object: { nested: { deep: true } }
};

const clone = structuredClone(original);

// 验证类型保持一致
console.log(clone.date instanceof Date);         // true
console.log(clone.regex instanceof RegExp);       // true
console.log(clone.map instanceof Map);           // true
console.log(clone.set instanceof Set);           // true
console.log(clone.arrayBuffer instanceof ArrayBuffer); // true
console.log(clone.typedArray instanceof Uint8Array);   // true

const clone2 = JSON.parse(JSON.stringify(original));
console.log(clone2.date instanceof Date); // false(变成字符串)
console.log(clone2.set instanceof Set);   // false(变成数组)

5、structuredClone()的兼容性判断

可以使用以下代码来安全地使用structuredClone(),在不支持的环境中自动退回到JSON方案(尽管功能会有所欠缺):

function deepClone(obj) {
  if (typeof structuredClone === 'function') {
    return structuredClone(obj);
  } else {
    // 备用方案:JSON克隆(注意功能有限)
    return JSON.parse(JSON.stringify(obj));
  }
}

二、structuredClone()与JSON.parse(JSON.stringify(obj))的区别

1、对比表格

特性 JSON.parse(JSON.stringify(obj)) structuredClone(obj)
深拷贝
性能 较慢(需要先序列化再解析) 更快(原生实现)
支持循环引用 报错 支持
支持类型丰富度 仅支持普通对象、数组、字符串、数字、布尔、null 支持更多类型(Map、Set、Blob、Date、File等)
丢失信息 会丢失函数、undefined、Symbol、日期、原型链等 保留更多原始结构
错误处理 容易出错(如循环引用会直接报错) 更安全,报错更明确

2、循环引用情况

循环引用指的是对象内部相互引用,形成“闭环”的结构,例如:

const obj = {};
obj.self = obj;
const cloned = structuredClone(obj); 

如果使用JSON.stringify(obj)就会报错:TypeError: Converting circular structure to JSON。但structuredClone()能够正确处理这种情况。

三、structuredClone()在性能上的提升

依据多个社区的实测benchmark(比如JSBench.me、V8团队博客以及真实项目测试):

  • 对于深层嵌套对象(10层以上),structuredClone()明显更快;
  • 对于包含Map、Set、Date、ArrayBuffer的复杂对象,structuredClone()能够直接处理,而JSON克隆则需要额外转换或者报错;
  • 平均测试中,structuredClone()比JSON快1.5到5倍,尤其在大型对象上提升更为显著。

四、结语

目前,structuredClone()已经被所有主流浏览器所支持。它为深拷贝问题提供了一个简便、高效的解决方案,赶快拥抱这个JavaScript新特性吧。

只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

相关文章

暂无评论

暂无评论...