Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

วิธีโคลนอ็อบเจกต์ JavaScript ยกเว้นคีย์บางตัว

วิธีที่ง่ายที่สุดคือ โคลนอ็อบเจกต์ทั้งหมดก่อน แล้วค่อยลบคีย์ที่ไม่ต้องการ การโคลนมี 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 (อ้างอิงวนรอบ)
  • สูญเสีย prototype chain

วิธี 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/SymbolJSON.parse(JSON.stringify(obj))
ต้องการ deep clone จริงๆ รองรับทุกชนิด (Modern)structuredClone(obj)
โปรเจกต์มี Lodash อยู่แล้ว_.cloneDeep(obj)