วิธีที่ง่ายที่สุดคือ โคลนอ็อบเจกต์ทั้งหมดก่อน แล้วค่อยลบคีย์ที่ไม่ต้องการ การโคลนมี 2 ประเภทหลัก:
1. Shallow Clone (โคลนตื้น)
คัดลอกโครงสร้างระดับบนสุดเท่านั้น อ็อบเจกต์/อาร์เรย์ซ้อนใน (nested) จะเป็น reference เดียวกัน
let innerObj = { a: 'b', c: 'd' };
let obj = { x: "test", y: innerObj };
// Shallow copy ด้วย Object.assign
let copyObj = Object.assign({}, obj);
// หรือ spread operator (ES6+)
let copyObj2 = { ...obj };
// ทั้ง copyObj และ obj คุณสมบัติ y ชี้ไป innerObj เดียวกัน
innerObj.a = "test";
console.log(obj); // { x: 'test', y: { a: 'test', c: 'd' } }
console.log(copyObj); // { x: 'test', y: { a: 'test', c: 'd' } } ← เปลี่ยนไปด้วย!
2. Deep Clone (โคลนลึก)
คัดลอกทุกระดับ รวมถึงอ็อบเจกต์/อาร์เรย์ซ้อนใน ทั้งสองอ็อบเจกต์แยกจากกันสมบูรณ์
let innerObj = { a: 'b', c: 'd' };
let obj = { x: "test", y: innerObj };
// Deep copy ด้วย JSON (มีข้อจำกัด - ดูด้านล่าง)
let copyObj = JSON.parse(JSON.stringify(obj));
innerObj.a = "test";
console.log(obj); // { x: 'test', y: { a: 'test', c: 'd' } }
console.log(copyObj); // { x: 'test', y: { a: 'b', c: 'd' } } ← ไม่เปลี่ยน! ✅
⚠️ ข้อจำกัดของ JSON.parse(JSON.stringify())
- ไม่รองรับ:
Function,undefined,Symbol,Date(กลายเป็น string),RegExp,Map,Set - ไม่รองรับ Circular References (อ้างอิงวนรอบ)
- สูญเสีย
prototypechain
วิธี Deep Clone ที่ทันสมัยกว่า
1. structuredClone() (Browser/Node 17+)
const deepCopy = structuredClone(original); // รองรับ Date, RegExp, Map, Set, ArrayBuffer, Circular refs ✅ // ไม่รองรับ Function, Symbol (เป็น design choice)
2. Lodash cloneDeep
const _ = require('lodash');
const deepCopy = _.cloneDeep(original);
ลบคีย์ที่ไม่ต้องการหลังโคลน
let original = { x: 'test', y: { a: 'test', c: 'd' } };
let copy = structuredClone(original); // หรือ JSON.parse(JSON.stringify(...))
delete copy['x']; // หรือ delete copy.x;
console.log(copy); // { y: { a: 'test', c: 'd' } }
console.log(original); // { x: 'test', y: { a: 'test', c: 'd' } } - ไม่ได้รับผลกระทบ
สรุปแนวทางเลือก
| สถานการณ์ | วิธีที่แนะนำ |
|---|---|
| อ็อบเจกต์เรียบ ไม่มี nested, ไม่มีฟังก์ชัน | {...obj} หรือ Object.assign({}, obj) |
| มี nested object/array, ไม่มี circular ref, ไม่มี function/Date/Symbol | JSON.parse(JSON.stringify(obj)) |
| ต้องการ deep clone จริงๆ รองรับทุกชนิด (Modern) | structuredClone(obj) |
| โปรเจกต์มี Lodash อยู่แล้ว | _.cloneDeep(obj) |