النسخ العميق للكائنات في JavaScript: أفضل 5 طرق

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا لا يعمل النسخ العادي؟

\n\n

تخيل أنك تكتب تطبيقًا يعالج إعدادات مستخدم معقدة. تقوم بـ const newConfig = oldConfig، وتغير بعض الحقول — وفجأة يتغير الكائن الأصلي أيضًا. ألم مألوف؟ 👋

\n\n

في JavaScript، يتم تمرير الكائنات بالمرجع. هذا يعني أن عملية التعيين البسيطة لا تنشئ كائنًا جديدًا، بل تنسخ المؤشر إلى الكائن القديم. ومن هنا يأتي السؤال الرئيسي الذي يؤرق آلاف المطورين على Stack Overflow: "ما هي الطريقة الأكثر كفاءة لعمل نسخة عميقة من كائن في JavaScript؟".

\n\n

في هذه المقالة، سنستعرض جميع الطرق الشائعة للنسخ العميق، مميزاتها، عيوبها، وأداءها. ستتعرف على الطريقة المناسبة لعام 2024، وستتعلم كتابة دالة deep clone موثوقة خاصة بك.

\n\n

لماذا نتحدث عن النسخ العميق؟

\n\n

النسخ العميق (deep clone) ينشئ نسخة مستقلة تمامًا من الكائن بجميع الهياكل المتداخلة. على عكس النسخ السطحي (shallow copy)، حيث تبقى الكائنات المتداخلة مشتركة.

\n\n

إليك سيناريو نموذجي تحتاج فيه إلى ذلك:

\n
    \n
  • العمل مع Redux / Zustand: لا يمكن تغيير الحالة، بل يجب إنشاء نسخ.
  • \n
  • تسلسل البيانات لإرسالها إلى الخادم.
  • \n
  • العمل مع ذاكرة التخزين المؤقت أو الإعدادات التي لا يمكن تعديلها.
  • \n
  • اختبارات الوحدة: لضمان عدم التأثير على البيانات الأصلية.
  • \n
\n\n

لكن الأمر ليس بهذه البساطة. إذا حاولت نسخ كائن يحتوي على دوال، أو undefined، أو Symbol، أو مراجع دائرية — فإن العديد من الطرق ستفشل أو تفقد البيانات. دعنا نستعرض كل طريقة بالتفصيل.

\n\n

الطريقة 1: JSON.parse(JSON.stringify(obj)) — قديمة ولكنها فعالة

\n\n

هذه هي الطريقة الأكثر شيوعًا بين المبتدئين. إنها بسيطة وسريعة الكتابة:

\n\n
const original = {\n    name: "آنا",\n    age: 25,\n    address: { city: "موسكو", zip: 101000 },\n    hobbies: ["قراءة", "جري"]\n};\n\nconst clone = JSON.parse(JSON.stringify(original));\n\nclone.address.city = "سانت بطرسبرغ";\nconsole.log(original.address.city); // "موسكو" — ✅ النسخة مستقلة!\n
\n\n

المميزات:

\n
    \n
  • 🔥 بناء جملة بسيط جدًا.
  • \n
  • 🔥 تعمل في معظم الحالات البسيطة.
  • \n
\n\n

العيوب (حرجة!):

\n
    \n
  • ❌ تفقد الدوال — ستتحول إلى undefined.
  • \n
  • ❌ تفقد undefined — الحقول التي قيمتها undefined ستختفي.
  • \n
  • ❌ تفقد Symbol — المفاتيح من نوع Symbol ستختفي.
  • \n
  • ❌ لا تعمل مع المراجع الدائرية — ستظهر خطأ TypeError.
  • \n
  • ❌ مشاكل مع التواريخ — Date ستتحول إلى نص.
  • \n
  • ❌ مشاكل مع Map, Set, RegExp — ستتحول إلى كائنات فارغة.
  • \n
\n\n

الخلاصة: مناسبة فقط للبيانات القابلة للتسلسل إلى JSON بشكل مضمون (نصوص، أرقام، مصفوفات، كائنات بسيطة).

\n\n

الطريقة 2: Structured Clone API — المعيار الحديث (2024)

\n\n

ابتداءً من عام 2022، ظهرت في JavaScript طريقة أصلية للنسخ العميق — structuredClone. وهي متاحة في جميع المتصفحات الحديثة و Node.js 17+.

\n\n
const clone = structuredClone(original);\n\nclone.address.city = "قازان";\nconsole.log(original.address.city); // "موسكو" — ✅\n
\n\n

ما يمكن لـ structuredClone فعله:

\n
    \n
  • ✅ المراجع الدائرية — تعمل!
  • \n
  • ✅ التواريخ — تحافظ على نوع Date.
  • \n
  • ✅ Map و Set — تنسخ بشكل صحيح.
  • \n
  • ✅ RegExp — تعمل أيضًا.
  • \n
  • ✅ ArrayBuffer و Ty
  • \n

المدونات

توصيات الكتب