Objectها بلوکهای بنیادی زبان JavaScript هستند. یک Object مجموعهای از propertyهاست و هر property ارتباطی بین یک key (نام) و یک value (مقدار) ایجاد میکند. تقریباً همهٔ Objectها در JavaScript نمونهای از Object هستند که در بالاترین سطح prototype chain قرار دارد.
مقدمه
همانطور که میدانید، assignment operator باعث ایجاد کپی از Object نمیشود و فقط یک reference به آن اختصاص میدهد. مثال:
متغیر obj شامل Object اصلی است و copy به همان Object اشاره میکند. یعنی این Object میگوید:
دو راه برای دسترسی به من وجود دارد: از طریق obj یا copy
هر تغییری از هر مسیر انجام شود، روی من اثر میگذارد.
امروزه مفهوم immutability بسیار مهم شده است. این روش (استفاده از reference) باعث از بین رفتن immutability میشود و اگر Object در بخش دیگری از کد استفاده شود، ممکن است باگ ایجاد کند.
روش ساده (Naive) برای کپی کردن Object
یک روش ساده این است که روی propertyهای Object حلقه بزنیم و آنها را یکییکی کپی کنیم:
مشکلات این روش
-
prototype کپی دقیقاً مثل prototype اصلی نیست
-
property descriptorها کپی نمیشوند
-
فقط propertyهای enumerable کپی میشوند
-
اگر property خودش Object باشد، فقط reference آن کپی میشود
Shallow Copy در Objectها
در shallow copy:
-
propertyهای سطح اول بدون reference کپی میشوند
-
اما Objectهای تو در تو همچنان reference مشترک دارند
استفاده از Object.assign()
متد Object.assign() تمام propertyهای enumerable را از source به target کپی میکند:
اگر مقدار objCopy را تغییر دهیم، obj اصلی تغییر نمیکند.
مشکل Object.assign()
اما اگر Object تو در تو داشته باشیم:
در این حالت مقدار داخل obj هم تغییر میکند، چون:
Object.assign فقط shallow copy انجام میدهد.
همچنین:
-
propertyهای prototype کپی نمیشوند
-
propertyهای non-enumerable کپی نمیشوند
Deep Copy در Objectها
در deep copy:
-
تمام Objectها به صورت کامل کپی میشوند
-
هیچ reference مشترکی باقی نمیماند
استفاده از JSON برای Deep Copy
مثال:
این روش deep copy واقعی ایجاد میکند.
مشکل این روش
این روش methodها (توابع داخل Object) را کپی نمیکند.
کپی کردن Object دارای Method
نتیجه:
-
Object.assign → method را کپی میکند
-
JSON → method را حذف میکند
کپی کردن Circular Object
Circular Object یعنی Objectی که به خودش reference دارد.
-
JSON.stringify برای این Objectها کار نمیکند
-
Object.assign فقط shallow copy میکند
استفاده از Spread Operator
در ES6 میتوان از spread استفاده کرد:
این هم فقط shallow copy است.
جمعبندی
کپی کردن Object در JavaScript ممکن است در ابتدا پیچیده به نظر برسد، مخصوصاً اگر تازهکار باشید. با شناخت تفاوتهای:
-
reference
-
shallow copy
-
deep copy
میتوانید از بسیاری از باگها جلوگیری کنید.
از همراهی شما با پارمین کلود سپاسگزاریم.
نظرات کاربران