物件、陣列、函式等多種資料型別的深淺克隆(拷貝)
阿新 • • 發佈:2022-03-28
物件(陣列)的深淺克隆
淺克隆
把
obj{ }
物件裡面的所有屬性拷貝到obj1{ }
中後,然後分別改變物件裡面的變數,原始值互不影響,引用值一個改變,另一個跟著變。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 淺克隆 // a、d 原始值; b、c 引用值 let obj = { a: 100, b: [10, 20, 30], c: { x: 10 }, d: /^\d+$/ }; // let obj2 = {...obj}; let obj2 = {}; for (let key in obj) { if (!obj.hasOwnProperty(key)) break; obj2[key] = obj[key]; } console.log(obj); // { a: 100, b: (3) [10, 20, 30], c: {x: 10}, d: /^\d+$/ } console.log(obj2); // { a: 100, b: (3) [10, 20, 30], c: {x: 10}, d: /^\d+$/ } obj2.a = 200; obj2.b[0] = 55; obj2.c["x"] = 66; obj2.d = /^\d-$/; console.log(obj); // { a: 100, b: (3) [55, 20, 30], c: {x: 66}, d: /^\d+$/ } console.log(obj2); // { a: 200, b: (3) [55, 20, 30], c: {x: 66}, d: /^\d-$/ } </script> </body> </html>
深克隆
修改引用值時,互不影響,你改我不變
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 深克隆 let obj = { a: 100, b: [10, 20, 30], c: { x: 10 }, d: /^\d+$/, e : function() { return 50; }, f: new Date(), g: new Map([["a", 1], ["b", 2], ["c", 3]]), h: new Set([1, 2, 3, 3, 4, {a : 10}]), i: null, j: undefined }; // 先轉為字串再轉回物件的過程會重新開闢記憶體空間 // 日期,函式,正則在轉為字串時會出現問題 // 函式(不輸出),正則(輸出空物件),時間物件(輸出時間字串),Undefiend(不輸出) let obj2 = JSON.parse(JSON.stringify(obj)); obj2.b[0] = 22; console.log(obj); // { a: 100, b: (3) [10, 20, 30], c: {x: 10}, d: /^\d+$/, e: ƒ e() } console.log(obj2); // { a: 100, b: (3) [22, 20, 30], c: {x: 10}, d: {}, [[Prototype]]: Object } function deepClone(obj) { // 處理null if (obj === null) return null; // 處理原始值 if (typeof obj != "object" && typeof obj != "function") return obj; // 處理函式 if (typeof obj === "function") { let func = obj + '' // 返回匿名函式 // new Function('...')() 直接執行引號中的內容,與eval return new Function('return ' + func)(); } // 處理正則 if (obj instanceof RegExp) { return new RegExp(obj); } // 處理Set物件 if (obj instanceof Set) { return new Set(obj); } // 處理Map物件 if (obj instanceof Map) { return new Map(obj); } // 處理日期 if (obj instanceof Date) { return new Date(obj); } // 用被克隆物件的建構函式建立一個例項,這樣克隆出來的物件也是那個建構函式的例項,保持相同的所屬類 let newObj = new obj.constructor; for (let key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = deepClone(obj[key]); } } return newObj; } let obj3 = deepClone(obj); console.log(obj); // { a: 100, b: (3) [10, 20, 30], c: {x: 10}, d: /^\d+$/, e: ƒ e() } console.log(obj3); // { a: 100, b: (3) [10, 20, 30], c: {x: 10}, d: /^\d+$/, e: ƒ e() } console.log(obj === obj3); // false console.log(obj.c === obj3.a); // false console.log(obj.e === obj3.b); // false console.log(obj.e === obj3.c); // false console.log(obj.e === obj3.d); // false console.log(obj.e === obj3.e); // false console.log(obj.e === obj3.f); // false console.log(obj.e === obj3.g); // false console.log(obj.e === obj3.h); // false console.log(obj.e === obj3.i); // false console.log(obj.e === obj3.j); // false </script> </body> </html>