Shallow Copy vs Deep Copy ใน JavaScript

JavaScript จัดการการคัดลอกในสองรูปแบบ ขึ้นอยู่กับประเภทของข้อมูล

ค่าแบบ Primitive (Copy by Value) ประเภทข้อมูลแบบ Primitive ได้แก่ strings, numbers, booleans, symbols, bigInt และ null เมื่อคุณคัดลอกค่าแบบ primitive JavaScript จะสร้างเวอร์ชันใหม่ที่เป็นอิสระต่อกันในหน่วยความจำ

ตัวอย่าง: let a = 10; let b = a; b = 20; ผลลัพธ์: a ยังคงเป็น 10

ค่าแบบ Non-Primitive (Copy by Reference) Object และ array ทำงานแตกต่างออกไป โดยจะใช้การอ้างอิง (references) เมื่อคุณคัดลอก object คุณเพียงแค่คัดลอกตัวชี้ (pointer) ไปยังตำแหน่งของมันในหน่วยความจำเท่านั้น

ตัวอย่าง: let original = { name: "YOO" }; let copy = original; copy.name = "NEW"; ผลลัพธ์: original.name กลายเป็น "NEW" แล้ว

ความแตกต่าง: Shallow vs Deep

Shallow copy จะคัดลอกเฉพาะข้อมูลในระดับบนสุด (top level) ของ object เท่านั้น หาก object นั้นมี object ซ้อนอยู่ข้างใน (nested objects) มันจะยังคงชี้ไปยังการอ้างอิงเดิมของข้อมูลที่ซ้อนอยู่นั้น Deep copy จะสร้าง object ใหม่ขึ้นมาทั้งหมดพร้อมกับค่าใหม่ทั้งหมด

ลองนึกภาพเหมือนพิซซ่า:

  • Shallow Copy: คุณและเพื่อนแชร์พิซซ่าถาดเดียวกัน ถ้าเพื่อนคุณกินไปหนึ่งชิ้น พิซซ่าของคุณก็จะเล็กลงด้วยเช่นกัน
  • Deep Copy: คุณทั้งคู่มีพิซซ่าแยกกันคนละถาด ถ้าเพื่อนคุณกินไปหนึ่งชิ้น พิซซ่าของคุณก็ยังเหมือนเดิม

วิธีการทำ Shallow Copy คุณสามารถใช้ spread operator (...) เพื่อทำ shallow copy ได้

let original = { name: "YOO", details: { age: 22 } }; let copy = { ...original };

คำเตือน: หากคุณเปลี่ยนค่า original.details.age ค่า copy.details.age ก็จะเปลี่ยนตามไปด้วย นี่คือกับดักของการทำ shallow copy

วิธีการทำ Deep Copy

  1. structuredClone() นี่เป็นฟังก์ชันที่มีมาให้ในตัว (built-in) ในเบราว์เซอร์สมัยใหม่และ Node.js ซึ่งสามารถจัดการกับโครงสร้างข้อมูลที่ซ้อนกันได้อย่างสมบูรณ์แบบ

ข้อดี:

  • รวดเร็วและเป็นแบบ native
  • รองรับ Dates, RegExp และ Maps

ข้อเสีย:

  • จะทำงานผิดพลาดหาก object นั้นมีฟังก์ชันหรือ DOM nodes อยู่ภายใน
  1. JSON.parse(JSON.stringify()) นี่เป็นเทคนิคเก่าแก่โดยการแปลง object ให้เป็น string แล้วแปลงกลับมาเป็น object อีกครั้ง

ทำไมถึงควรหลีกเลี่ยง:

  • ข้อมูลบางอย่างจะหายไป เช่น undefined, Map, Set หรือ Infinity
  • อาจทำให้ค่าบางอย่างผิดเพี้ยนไป

แหล่งที่มา: https://dev.to/yogesh_992/shallow-copy-vs-deep-copy-in-java-script-explained-in-easiest-way-3dg5