最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS原生深拷貝的終極方案structuredClone用法代碼示例

 更新時間:2026年05月27日 11:39:40   作者:代碼里的小貓咪  
structuredClone()是JavaScript中用于創(chuàng)建對象深拷貝的原生方法,相比JSON.parse等傳統(tǒng)方法,它能更全面地處理復雜數(shù)據(jù)類型,這篇文章主要介紹了JS原生深拷貝的終極方案structuredClone用法的相關資料,需要的朋友可以參考下

前言

在 JavaScript 開發(fā)中,對象的深拷貝一直是一個經(jīng)典痛點。從 JSON.parse(JSON.stringify()) 的 hack,到 Lodash 的 _.cloneDeep(),開發(fā)者們一直在找一個既可靠又高效的深拷貝。2022 年,structuredClone 作為全局 API 正式進入所有主流瀏覽器和 Node.js,終結了這場漫長的探索。

1. 基本用法

const original = {
  name: 'Alice',
  scores: [95, 87, 92],
  metadata: {
    createdAt: new Date(),
    pattern: /hello/gi,
  },
};

const cloned = structuredClone(original);

cloned.scores.push(100);
console.log(original.scores); // [95, 87, 92] — 互不影響
console.log(cloned.metadata.createdAt instanceof Date); // true — 類型保留
console.log(cloned.metadata.pattern instanceof RegExp); // true

一行代碼,深拷貝完成。沒有序列化/反序列化的中間步驟,沒有第三方依賴。

Transfer 參數(shù)

structuredClone 的第二個參數(shù)支持 transfer 選項,這是它相比其他深拷貝方案的獨特能力:

const buffer = new ArrayBuffer(1024 * 1024 * 100); // 100MB

// 傳統(tǒng)克?。簭椭?100MB 內存
const cloned = structuredClone(buffer);

// Transfer:所有權轉移,零拷貝
const transferred = structuredClone(buffer, { transfer: [buffer] });

console.log(buffer.byteLength); // 0 
console.log(transferred.byteLength); // 104857600

Transfer 的本質是所有權轉移(ownership transfer),不是復制。底層只是修改了內存區(qū)域的歸屬指針,時間復雜度 O(1)。

為什么要這樣設計?

核心原因是性能。如果要把 100MB 的視頻幀數(shù)據(jù)發(fā)給 Web Worker 處理:

// 方式 1:復制(慢,瞬間多占 100MB 內存)
worker.postMessage(buffer);

// 方式 2:轉移(瞬間完成,內存不增長)
worker.postMessage(buffer, [buffer]);
// 但此后主線程不能再用這個 buffer 了

Transfer 的代價是:原始變量變成一個"空殼"(規(guī)范稱為 detached / neutered)。這是一個權衡——用"獨占訪問權"換來了"零拷貝性能"。

2. 支持/行為

這是 structuredClone 最大的優(yōu)勢所在。

  • 支持:普通對象、數(shù)組、Date、Map、Set、RegExp、ArrayBuffer、TypedArray、Blob、File、BigInt、循環(huán)引用等
  • 不支持/會報 DataCloneError(典型):
    • function,函數(shù)閉包綁定了執(zhí)行上下文,無法序列化
    • WeakMap/WeakSet,弱引用語義不允許枚舉
    • Proxy(Vue reactive 就在這)
    • DOM Nodes,綁定了渲染樹,跨上下文無意義
  • 保留對象圖結構:可保留“同一引用關系”和循環(huán)結構

關鍵:原型鏈丟失

class Vector {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  magnitude() {
    return Math.sqrt(this.x ** 2 + this.y ** 2);
  }
}

const v = new Vector(3, 4);
const cloned = structuredClone(v);

console.log(cloned.x); // 3
console.log(cloned.magnitude); // undefined 
console.log(Object.getPrototypeOf(cloned) === Vector.prototype); // false
console.log(Object.getPrototypeOf(cloned) === Object.prototype); // true

structuredClone 克隆的是數(shù)據(jù),不是行為。

對比 JSON.parse(JSON.stringify()) 支持/行為

  • 支持:普通對象、數(shù)組、字符串、數(shù)字、布爾、null
  • 會丟失/變化:
    • undefined(對象屬性會被丟棄)
    • function(丟棄)
    • symbol(丟棄)
    • Date -> 字符串(ISO)
    • Map/Set -> 通常變空對象或丟信息
    • RegExp -> 普通對象/空對象
    • NaN/Infinity/-Infinity -> null
    • BigInt -> 直接報錯(TypeError)
  • 循環(huán)引用:直接報錯 Converting circular structure to JSON

循環(huán)引用

這是 structuredClone 相比 JSON 方案的核心優(yōu)勢之一:

const obj = { name: 'root' };
obj.self = obj;
obj.children = [{ parent: obj }];

// JSON 方案直接爆炸
// JSON.stringify(obj); // TypeError: Converting circular structure to JSON

// structuredClone 優(yōu)雅處理
const cloned = structuredClone(obj);
console.log(cloned.self === cloned); // true
console.log(cloned.children[0].parent === cloned); // true
console.log(cloned !== obj); // true 

算法內部維護了一個 (source, clone) 的映射表。當遍歷到已經(jīng)克隆過的對象時,直接返回映射表中的克隆體,從而:

  • 避免無限遞歸
  • 保持引用拓撲結構的一致性

3. 底層原理

JSON 方案底層原理

JSON.stringify(ECMAScript JSON 序列化算法)做的事:

  • 遍歷對象可序列化屬性
  • 處理 toJSON(如 Date 會先轉字符串)
  • 生成 JSON 文本(UTF-16 JS 字符串)

JSON.parse 做的事:

  • 詞法/語法解析 JSON 文本
  • 構建全新 JS 對象樹
  • 可選 reviver 二次轉換

本質:文本協(xié)議往返。

structuredClone 底層原理

基于 HTML 標準里的 Structured Clone Algorithm(瀏覽器/運行時實現(xiàn)):

  • 從源對象圖開始遍歷
  • 維護“已訪問對象表”(解決循環(huán)與共享引用
  • 按對象類型走不同克隆分支(Map/Set/Date/TypedArray 等)
  • 生成克隆對象圖并重建引用關系
  • 可選 transfer 列表:對可轉移對象“轉移所有權”(原對象 detach)

本質:對象圖語義復制(不是文本)。

4. 一句話總結

1、JSON.parse(JSON.stringify(obj)):本質是先序列化成 JSON 文本,再解析回對象,是“文本中轉”。

2、structuredClone(obj):本質是按結構化克隆算法直接復制內存對象圖,不是 JSON 文本中轉。

附:structuredClone () 與其他克隆方法詳細對比

與 JSON.parse (JSON.stringify ()) 對比

在 JavaScript 中,JSON.parse(JSON.stringify()) 是一種常用的實現(xiàn)深拷貝的方法,但它與 structuredClone() 存在諸多差異。

在支持的數(shù)據(jù)類型方面,JSON.parse(JSON.stringify()) 僅支持基本數(shù)據(jù)類型(如數(shù)字、字符串、布爾值)、普通對象和數(shù)組 。對于 Date 對象,它會將其轉換為字符串,在反序列化后不再是 Date 對象,而是普通字符串;Map、Set、RegExp 對象會被轉換為空對象;函數(shù)、undefined、symbol、Infinity、NaN 以及循環(huán)引用等都無法正確處理 。而 structuredClone() 支持的數(shù)據(jù)類型更為廣泛,除了基本數(shù)據(jù)類型和普通對象、數(shù)組外,還支持 Date、RegExp、Map、Set、ArrayBuffer、TypedArrays、Blob、File、ImageData、MessagePort 等,并且能正確處理循環(huán)引用 。例如:

// JSON.parse(JSON.stringify()) 處理不支持的類型
const original1 = {
date: new Date(),
map: new Map([['key1', 'value1']]),
func: function() { return 'function' }
};
const jsonClone1 = JSON.parse(JSON.stringify(original1));
console.log(jsonClone1.date instanceof Date); // false,Date 被轉為字符串
console.log(jsonClone1.map instanceof Map); // false,Map 被轉為空對象
console.log(jsonClone1.func); // undefined,函數(shù)丟失
// structuredClone() 處理支持的類型
const original2 = {
date: new Date(),
map: new Map([['key1', 'value1']]),
arrayBuffer: new Uint8Array([1, 2, 3]).buffer
};
const structuredClone2 = structuredClone(original2);
console.log(structuredClone2.date instanceof Date); // true
console.log(structuredClone2.map instanceof Map); // true
console.log(structuredClone2.arrayBuffer instanceof ArrayBuffer); // true

在循環(huán)引用處理上,JSON.parse(JSON.stringify()) 無法處理對象中的循環(huán)引用,當對象存在循環(huán)引用時,調用 JSON.stringify() 會拋出 TypeError: Converting circular structure to JSON 錯誤 ,導致克隆失敗。而 structuredClone() 可以正確處理循環(huán)引用,確??寺『蟮膶ο蟀_的循環(huán)引用結構,不會陷入無限循環(huán) 。比如:

// JSON.parse(JSON.stringify()) 處理循環(huán)引用
let obj1 = {};
let obj2 = { ref: obj1 };
obj1.ref = obj2;
try {
const jsonClone = JSON.parse(JSON.stringify(obj1));
} catch (error) {
console.error('JSON.parse(JSON.stringify())循環(huán)引用錯誤:', error); // 拋出錯誤
}
// structuredClone() 處理循環(huán)引用
let obj3 = {};
let obj4 = { ref: obj3 };
obj3.ref = obj4;
const structuredClone3 = structuredClone(obj3);
console.log(structuredClone3.ref === structuredClone3.ref.ref); // true,循環(huán)引用處理正確

性能方面,JSON.parse(JSON.stringify()) 在處理簡單的、JSON 兼容的數(shù)據(jù)結構時性能尚可,但在處理復雜對象或包含大量非 JSON 兼容類型的數(shù)據(jù)時,由于需要進行序列化和反序列化操作,效率較低 。structuredClone() 是為深度克隆設計的原生方法,內部針對復雜場景進行了優(yōu)化,通常在處理復雜對象時性能更優(yōu) 。通過以下測試可以明顯看出兩者的性能差異:

// 性能測試
const largeArray = new Array(10000).fill({ key: 'value' });
console.time('JSON.parse(JSON.stringify())');
const jsonClone = JSON.parse(JSON.stringify(largeArray));
console.timeEnd('JSON.parse(JSON.stringify())');
console.time('structuredClone');
const structuredClone4 = structuredClone(largeArray);
console.timeEnd('structuredClone');

在瀏覽器兼容性上,JSON.parse(JSON.stringify()) 在現(xiàn)代瀏覽器和較舊的瀏覽器中都有廣泛支持 。而 structuredClone() 是一種較新的 API,在某些較舊的瀏覽器中不被支持 ,使用時需要考慮兼容性問題,可以通過檢測 typeof structuredClone === 'function' 來判斷瀏覽器是否支持該方法,不支持時可采用其他替代方案。

到此這篇關于JS原生深拷貝的終極方案structuredClone用法代碼示例的文章就介紹到這了,更多相關JS原生深拷貝structuredClone內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 通過js控制修改css變量的具體示例

    通過js控制修改css變量的具體示例

    在網(wǎng)頁開發(fā)中我們通常使用CSS來設置網(wǎng)頁的樣式,但是,在開發(fā)過程中,有時候我們需要根據(jù)不同的條件來動態(tài)修改樣式,這篇文章主要介紹了通過js控制修改css變量的具體示例,需要的朋友可以參考下
    2025-04-04
  • es7中的async、await使用方法示例詳解

    es7中的async、await使用方法示例詳解

    async、await是es7里面的新語法,async申明一個function是異步,而await等待一個異步方法執(zhí)行完成。替代promise中的then。async函數(shù)返回一個Promise對象,當函數(shù)執(zhí)行的時候,一旦遇到await就會先返回,等到觸發(fā)的異步操作完成,再接著執(zhí)行函數(shù)體內后面的語句。
    2023-01-01
  • javascript基于prototype實現(xiàn)類似OOP繼承的方法

    javascript基于prototype實現(xiàn)類似OOP繼承的方法

    這篇文章主要介紹了javascript基于prototype實現(xiàn)類似OOP繼承的方法,實例分析了JavaScript使用prototype實現(xiàn)面向對象程序設計的中類繼承的相關技巧,需要的朋友可以參考下
    2015-12-12
  • 微信小程序實現(xiàn)通過雙向滑動縮放圖片大小的方法

    微信小程序實現(xiàn)通過雙向滑動縮放圖片大小的方法

    這篇文章主要介紹了微信小程序實現(xiàn)通過雙向滑動縮放圖片大小的方法,結合實例形式分析了微信小程序事件響應及圖片元素屬性動態(tài)操作相關實現(xiàn)技巧,需要的朋友可以參考下
    2018-12-12
  • BootStrap表單控件之文本域textarea

    BootStrap表單控件之文本域textarea

    這篇文章主要介紹了BootStrap表單控件之文本域textarea,需要的朋友可以參考下
    2017-05-05
  • javascript實現(xiàn)自由編輯圖片代碼詳解

    javascript實現(xiàn)自由編輯圖片代碼詳解

    這篇文章主要介紹了javascript實現(xiàn)自由編輯圖片代碼詳解,在當下的的前端項目中,圖片功能可以說是非常常見的,圖片的展示、圖片的裁剪編輯、圖片的上傳等,那么我們的項目便來了個需求。,需要的朋友可以參考下
    2019-06-06
  • JavaScript列表框listbox全選和反選的實現(xiàn)方法

    JavaScript列表框listbox全選和反選的實現(xiàn)方法

    這篇文章主要介紹了JavaScript列表框listbox全選和反選的實現(xiàn)方法,涉及javascript操作列表框listbox的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • JavaScript定義和初始化二維數(shù)組的三種常用方法

    JavaScript定義和初始化二維數(shù)組的三種常用方法

    這篇文章主要介紹了在 JavaScript 中定義和初始化二維數(shù)組的三種常用方法,并通過示例代碼和實際應用場景進行解釋,幫助開發(fā)者深入理解其使用技巧和注意事項,需要的朋友可以參考下
    2025-12-12
  • JS DOM 操作實現(xiàn)代碼

    JS DOM 操作實現(xiàn)代碼

    JS DOM 操作實現(xiàn)代碼,學習dom操作的朋友可以參考下。
    2010-08-08
  • js實現(xiàn)拖拽上傳圖片功能

    js實現(xiàn)拖拽上傳圖片功能

    這篇文章主要為大家詳細介紹了js實現(xiàn)拖拽上傳圖片功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評論

汤阴县| 玛多县| 南靖县| 乌兰浩特市| 威宁| 临沭县| 宁波市| 额尔古纳市| 江西省| 平泉县| 惠来县| 广西| 沙坪坝区| 文山县| 新化县| 中超| 大名县| 长乐市| 榆中县| 姜堰市| 巩义市| 德安县| 罗田县| 上饶县| 庆云县| 来安县| 宁乡县| 长宁区| 滦平县| 田阳县| 冷水江市| 东海县| 习水县| 商水县| 舒兰市| 宕昌县| 桑日县| 齐齐哈尔市| 翼城县| 云霄县| 旺苍县|