30天JS挑戰(第十四天)------數據的復制

第十四天挑戰(數據的復制)

地址:https://javascript30.com/

所有內容均上傳至gitee,答案不唯一,僅代表本人思路

中文詳解:https://github.com/soyaine/JavaScript30

該詳解是Soyaine及其團隊整理編撰的,是對源代碼的詳解強烈推薦大家觀看學習!!!

本人gitee:https://gitee.com/thats-all-right-ha-ha/30-days—js-challenge

官方代碼

本期內容是關于基本數據類型和引用數據類型在復制時的特性和解決方法

基礎類型

//start with strings, numbers and booleans
let age = 100;
let age2 = age;
console.log(age, age2);
age = 200;
console.log(age, age2);let name = 'Wes';
let name2 = name;
console.log(name, name2);
name = 'wesley';
console.log(name, name2);

分析

  • 基礎數據類型:
    • 布爾值(Boolean),有 2 個值分別是:truefalse
    • null,一個表明 null 值的特殊關鍵字。JavaScript 是大小寫敏感的,因此 nullNullNULL或變體完全不同。
    • undefined,和 null 一樣是一個特殊的關鍵字,undefined 表示變量未賦值時的屬性。
    • 數字(Number),整數或浮點數,例如: 42 或者 3.14159
    • 任意精度的整數(BigInt),可以安全地存儲和操作大整數,甚至可以超過數字的安全整數限制。
    • 字符串(String),字符串是一串表示文本值的字符序列,例如:"Howdy"
    • 代表(Symbol,在 ECMAScript 6 中新添加的類型)。一種實例是唯一且不可改變的數據類型。
  • 基礎數據類型的值均存儲在棧中,每個值都有一個獨立的內存空間,在a變量復制給b變量的時候復制的是一個具體的值,在a變量進行更改的時候,不會影響到b變量的值

引用類型(數組)

// Let's say we have an array
const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];// and we want to make a copy of it.
const team = players;console.log(players, team);
// You might think we can just do something like this:
// team[3] = 'Lux';// however what happens when we update that array?// now here is the problem!// oh no - we have edited the original array too!// Why? It's because that is an array reference, not an array copy. They both point to the same array!// So, how do we fix this? We take a copy instead!
const team2 = players.slice();// one way// or create a new array and concat the old one in
const team3 = [].concat(players);// or use the new ES6 Spread
const team4 = [...players];
team4[3] = 'heeee hawww';
console.log(team4);const team5 = Array.from(players);// now when we update it, the original one isn't changed

分析

  • 引用類型(數組)
  • 一般情況下引用類型的值會作為數據的有序或無序集合即一個數組中包含著許多的數據,通常他們的數據體量都較為龐大,所以一般引用類型的數據都存放在堆內存中,并且在棧內存中開辟一個地址單元指向其堆內存中的地址
  • 在數組進行復制的時候,本質上復制的是數組在堆內存中的地址,也就是 teamplayers這兩個變量指向的是同一個數組,那么當其中一個對其進行改變的時候,另一個也會受到一定的影響
  • 那么如何解決這個問題?
    • slice方法:slice方法會返回一個新的數組,這個數組的值是原數組的淺拷貝,slice的返回的數組和原數組是兩個數組,不會造成影響
    • concat:方法用于合并兩個或多個數組。此方法不會更改現有數組,而是返回一個新數組
    • 展開運算符
    • 創建新的數組實例

引用類型(對象)

// with Objects
const person = {
name: 'Wes Bos',
age: 80
};// and think we make a copy:
// const captain = person;
// captain.number = 99;// how do we take a copy instead?
const cap2 = Object.assign({}, person, { number: 99, age: 12 });
console.log(cap2);// We will hopefully soon see the object ...spread
// const cap3 = {...person};// Things to note - this is only 1 level deep - both for Arrays and Objects. lodash has a cloneDeep method, but you should think twice before using it.const wes = {
name: 'Wes',
age: 100,
social: {
twitter: '@wesbos',
facebook: 'wesbos.developer'
}
};console.clear();
console.log(wes);const dev = Object.assign({}, wes);const dev2 = JSON.parse(JSON.stringify(wes));

分析

  • 對象也是引用類型,和數組的存儲原理基本一致,這里直接上解決方法
  • 解決方法
  • Object.assign():將一個或者多個源對象中所有可枚舉的自有屬性復制到目標對象,并返回修改后的目標對象。
  • JSON.parse & JSON.stringify:后者將對象轉換成字符串,前者將字符串再復原成對象

擴展知識

引用類型的深拷貝

數組和對象的深拷貝在JavaScript中是一個常見需求,尤其是在處理復雜數據結構時,以確保原始數據不被無意修改。深拷貝意味著復制對象及其嵌套對象的實際值,而不僅僅是復制引用地址。以下是實現深拷貝的幾種方法:

1. 使用 JSON.stringify()JSON.parse()

這種方法簡單易用,但是有其局限性,比如不能復制函數、undefined、Symbol、循環引用等。

javascriptCopy codeconst obj = {a: 1,b: {c: 2,d: 3,},
};const arr = [1, [2, 3], { a: 4 }];const deepCopiedObj = JSON.parse(JSON.stringify(obj));
const deepCopiedArr = JSON.parse(JSON.stringify(arr));// 修改深拷貝后的對象和數組,不會影響原始數據
deepCopiedObj.b.c = 20;
deepCopiedArr[1][0] = 200;console.log(obj.b.c); // 輸出 2
console.log(arr[1][0]); // 輸出 2

2. 使用遞歸

遞歸方法可以更靈活地處理各種數據類型,包括數組和對象,但需要手動實現。

javascriptCopy codefunction deepCopy(value, hash = new WeakMap()) {if (typeof value !== 'object' || value === null) {return value;}if (hash.has(value)) {return hash.get(value);}let copy = Array.isArray(value) ? [] : {};hash.set(value, copy);for (let key in value) {if (value.hasOwnProperty(key)) {copy[key] = deepCopy(value[key], hash);}}return copy;
}const obj = { a: 1, b: { c: 2 } };
const arr = [1, [2, 3], { a: 4 }];const deepCopiedObj = deepCopy(obj);
const deepCopiedArr = deepCopy(arr);deepCopiedObj.b.c = 20;
deepCopiedArr[1][0] = 200;console.log(obj.b.c); // 輸出 2
console.log(arr[1][0]); // 輸出 2

3. 使用 structuredClone()

從 ES2021 開始,structuredClone() 方法提供了一種官方、高效的深拷貝解決方案,支持大多數數據類型,包括循環引用,但不支持復制函數。

javascriptCopy codeconst obj = { a: 1, b: { c: 2 } };
const arr = [1, [2, 3], { a: 4 }];const deepCopiedObj = structuredClone(obj);
const deepCopiedArr = structuredClone(arr);deepCopiedObj.b.c = 20;
deepCopiedArr[1][0] = 200;console.log(obj.b.c); // 輸出 2
console.log(arr[1][0]); // 輸出 2

structuredClone() 是目前最推薦的深拷貝實現方式,因為它既能處理復雜數據結構,包括循環引用,又能通過瀏覽器和Node.js環境的標準API直接使用。不過,它可能不適用于舊版瀏覽器或某些特殊環境,需要根據實際情況選擇合適的方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717867.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717867.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717867.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

后端開發技術面試指南

工作10多年,每年都會幫組里面試一些新同學校招社招的都有,下面我就從一個面試官的視角來給大家拆解一下如何淡然應對后端開發技術面試。 1.一面多為電話面試 (1)問七問八 ①簡歷要注重內容,形式上不丑沒有錯別字即可。之前收到過一個工作5…

經典語義分割(一)利用pytorch復現全卷積神經網絡FCN

經典語義分割(一)利用pytorch復現全卷積神經網絡FCN 這里選擇B站up主[霹靂吧啦Wz]根據pytorch官方torchvision模塊中實現的FCN源碼。 Github連接:FCN源碼 1 FCN模型搭建 1.1 FCN網絡圖 pytorch官方實現的FCN網絡圖,如下所示。 1.2 backbone FCN原…

為raspberrypi編譯bpftrace調試工具

基于eBPF的嵌入式應用調試 筆者之前寫過幾篇有關于使用eBPF調試Linux內核和應用的博客,其中提到,在嵌入式設備上使用BCC或bpftrace是不可行的;主要原因在于嵌入式設備的資源有限,而這兩個調試工具依賴python/clang/llvm等庫&…

Scratch 第十六課-彈珠臺游戲

第十六課-彈珠臺游戲 大家好,今天我們一起做一款彈珠臺scratch游戲,我們也可以叫它彈球游戲!這款游戲在剛出來的時候非常火爆。小朋友們要認真學習下! 這節課的學習目標 物體碰撞如何處理轉向問題。復習鍵盤對角色的控制方式。…

STL-內存的配置與釋放

STL-內存的配置與釋放 STL有兩級空間配置器,默認是使用第二級。第二級空間配置器會在某些情況下去調用第一級空間配置器。空間配置器都是在allocate函數內分配內存,在deallocate函數內釋放內存。 第一級空間配置器 第一級配置器只是對malloc函數和fre…

【自然語言處理】BitNet b1.58:1bit LLM時代

論文地址:https://arxiv.org/pdf/2402.17764.pdf 相關博客 【自然語言處理】BitNet b1.58:1bit LLM時代 【自然語言處理】【長文本處理】RMT:能處理長度超過一百萬token的Transformer 【自然語言處理】【大模型】MPT模型結構源碼解析(單機版)…

如何在 Mac 上成功輕松地恢復 Excel 文件

Microsoft Excel 的 Mac 版本始終略落后于 Windows 版本,這也許可以解釋為什么如此多的用戶渴望學習如何在 Mac 上恢復 Excel 文件。 但導致重要電子表格不可用的不僅僅是 Mac 版 Excel 的不完全穩定性。用戶有時會失去注意力并刪除錯誤的文件,存儲設備…

2024-03-03 c++

🌸 MFC進度條控件 | Progress Control 1。新建MFC項目(基于對話框、靜態庫) 2。添加控件,刪除初始的3個多余控件 加1個progress control,修改其marquee為true,添加變量:變量名為test_progress。…

Angular基礎---HelloWorld---Day1

文章目錄 1. 創建Angular 項目2.對Angular架構的最基本了解3.創建并引用新的組件(component)4.對Angular架構新的認識(多組件)5.組件中業務邏輯文件的編輯(ts文件)6.標簽中屬性的綁定(1) ID的綁定(2) class…

String和String Builder

String和StringBuilder的區別 String類 String類代表字符串。java程序中所有字符串文字(例如“abc”)都被實現為此類的實例。 String類源碼是用final修飾的,它們的值在創建后不能被更改。字符串緩沖區支持可變字符串。 String對象是不可變…

STM32 (2)

1.stm32編程模型 將C語言程序燒錄到芯片中會存儲在單片機的flsah存儲器中,給芯片上電后,Flash中的程序會逐條進入到CPU中去執行,進而CPU去控制各種模塊(即外設)去實現各種功能。 2.寄存器和寄存器編程 CPU通過控制其…

Apache POI的簡單介紹與應用

介紹 Apache POI 是一個處理Miscrosoft Office各種文件格式的開源項目。我們可以使用 POI 在 Java 程序中對Miscrosoft Office各種文件進行讀寫操作。PS: 一般情況下,POI 都是用于操作 Excel 文件,如圖: Apache POI 的應用場景&…

SQL無列名注入

SQL無列名注入 ? 前段時間,隊里某位大佬發了一個關于sql注入無列名的文章,感覺好像很有用,特地研究下。 關于 information_schema 數據庫: ? 對于這一個庫,我所知曉的內容并不多,并且之前總結SQL注入的…

設計模式-橋接模式實踐案例

橋接模式(Bridge Pattern)是一種結構型設計模式,用于將抽象與實現分離,使它們可以獨立地變化。這種模式通過提供一個橋接結構,可以將實現接口的實現部分和抽象層中可變化的部分分離開來。 以下是一個使用 Java 實現橋…

【數據結構】_包裝類與泛型

目錄 1. 包裝類 1.1 基本數據類型和對應的包裝類 1.2 (自動)裝箱和(自動)拆箱 1.2.1 裝箱與拆箱 1.2.2 自動(顯式)裝箱與自動(顯式)拆箱 1.3 valueOf()方法 2. 泛型類 2.1 泛…

【深度學習筆記】計算機視覺——目標檢測和邊界框

目標檢測和邊界框 前面的章節(例如 sec_alexnet— sec_googlenet)介紹了各種圖像分類模型。 在圖像分類任務中,我們假設圖像中只有一個主要物體對象,我們只關注如何識別其類別。 然而,很多時候圖像里有多個我們感興趣…

某大型制造企業數字化轉型規劃方案(附下載)

目錄 一、項目背景和目標 二、業務現狀 1. 總體應用現狀 2. 各模塊業務問題 2.1 設計 2.2 仿真 2.3 制造 2.4 服務 2.5 管理 三、業務需求及預期效果 1. 總體業務需求 2. 各模塊業務需求 2.1 設計 2.2 仿真 2.3 制造 2.4 服務 2.5 管理 四、…

在vue中對keep-alive的理解,它是如何實現的,具體緩存的是什么?

對keep-alive的理解,它是如何實現的,具體緩存的是什么? (1)keep-alive有以下三個屬性:注意:keep-alive 包裹動態組件時,會緩存不活動的組件實例。主要流程 (2&#xff09…

數字化轉型導師堅鵬:證券公司數字化營銷

證券公司數字化營銷 ——借力數字化技術實現零售業務的批量化、精準化、場景化、智能化營銷 課程背景: 很多證券公司存在以下問題: 不知道如何提升證券公司數字化營銷能力? 不知道證券公司如何開展數字化營銷工作? 不知道…

胎神游戲集第二期

延續上一期 一、海島奇胎 #include<bits/stdc.h> #include<windows.h> #include<stdio.h> #include<conio.h> #include<time.h> using namespace std; typedef BOOL (WINAPI *PROCSETCONSOLEFONT)(HANDLE, DWORD); PROCSETCONSOLEFONT SetCons…