۱. تعریف اولیه (برای شروع صحبت):
«در جاوااسکریپت، وقتی از آبجکتها یا آرایهها کپی میگیریم، باید به دو نوع کپی دقت کنیم: Shallow Copy و Deep Copy. تفاوت اصلی در این است که یک کپی چقدر از آبجکت اصلی مستقل میشود.»
۲. تفاوت مفهومی (با مثال ساده):
«در Shallow Copy یا کپی سطحی، فقط خود آبجکت اصلی در یک آدرس جدید ساخته میشود، اما اگر داخل آبجکت، آبجکتهای تو در تو (یا آرایه) داشته باشیم، آنها هنوز به همان حافظهٔ قبلی اشاره میکنند. یعنی اگر مقدار یک آبجکت تو در تو را تغییر دهم، آن تغییر در هر دو نسخه (اصلی و کپی) دیده میشود.»
«در Deep Copy یا کپی عمیق، همهچیز از اول و بهصورت کامل کپی میشود. دیگر هیچ اشارهای به آبجکت اصلی نداریم و تغییر در کپی، روی اصل تأثیر نمیگذارد و برعکس.»
۳. روشهای معمول (با ذکر محدودیتها):
«برای کپی سطحی معمولاً از اسپرید (
...) یاObject.assignاستفاده میکنیم.»«برای کپی عمیق، خیلیها از دو روش استفاده میکنند: یکی
JSON.stringifyبه همراهJSON.parseو دیگری تابعstructuredCloneکه جدیدتر است.»«اما نکتهی مهم اینجاست که هیچکدام از این دو روش کامل نیستند و محدودیتهای مشخصی دارند.»
۴. مشکل اصلی (همان سوال کلیدی مصاحبه):
«مشکل اول با
JSON.stringify/parse: این روش فقط دادههایی را پشتیبانی میکند که فرمت JSON داشته باشند. یعنی توابع،undefined،Symbol، تاریخ (Date) و بعضی از آبجکتهای خاص مثلMapوSetرا از دست میدهد یا تبدیل اشتباهی انجام میدهد. مثلاً تاریخ را به رشته تبدیل میکند و دیگر یک شیء تاریخ نمیماند.»«مشکل دوم با
structuredClone: این تابع خیلی بهتر است و از تاریخ،Map،Setو حتی دادههای باینری پشتیبانی میکند. اما باز هم کامل نیست؛ مثلاً توابع را نمیتواند کپی کند و اگر آبجکت شما شامل توابع یاSymbolباشد، خطا میدهد. همچنین بعضی از آبجکتهای خاص مثلErrorیاElement(DOM) را هم پشتیبانی نمیکند.»
۵. جمعبندی نهایی (برای نشان دادن تسلط):
«پس بهطور خلاصه، اگر دادهی ما فقط شامل اشیاء ساده و JSON-friendly است،
structuredCloneانتخاب خوبی است. اما اگر داده شامل توابع، سمبلها، یا آبجکتهای غیرقابلسریالسازی است، باید از کتابخانههای تخصصی مثل Lodash با متدcloneDeepاستفاده کنیم، یا خودمان کپیعمیق را بهصورت بازگشتی پیادهسازی کنیم.»«نکتهی کلیدی که باید به خاطر داشته باشیم این است که هیچ روش داخلی در جاوااسکریپت برای کپی عمیق ۱۰۰٪ کامل وجود ندارد و انتخاب روش به نوع دادهی ما بستگی دارد.»
کاربرد structuredClone: در Web Workers یا برای ذخیرهسازی دادهها خیلی مفید است چون از ساختارهای جدید پشتیبانی میکند.
تفاوت structuredClone با JSON: دومی سریعتر است ولی اولی امنتر و کاملتر برای دادههای مدرن جاوااسکریپت.
راهحل نهایی: اگر کتابخانهای مثل Lodash مجاز نیست، میتوانیم یک تابع بازگشتی بنویسیم که نوع داده را چک کند و برای هر نوع (آرایه، آبجکت، Map، Set و ...) کپی مخصوص خودش را انجام دهد.
اگر بخواهی این متن را با لحن خودت و با مثال عملی کوتاه هم همراه کنی، خیلی تأثیرگذارتر خواهد شد. مثلاً:
«مثلاً اگر من یک آبجکت داشته باشم که داخلش یک تاریخ (
new Date()) باشد و ازJSON.stringifyاستفاده کنم، آن تاریخ به یک رشته تبدیل میشود و وقتی دوباره پارس میکنم، دیگر یک شیء تاریخ نیست و متدهایgetMonthیاgetFullYearروی آن کار نمیکند.»