في البرمجة، يشير تغيير كائن إلى أن حالة الكائن أو بياناته قد تغيرت بعد إنشائه. بمعنى آخر، العملية التي تغير سمات الكائن في JavaScript تعرف بتغيير الكائن. تغيير الكائن يعدل قيم الكائن مباشرة، مما يجعل الأمر صعبًا، خصوصًا في التطبيقات التي قد تحاول فيها عمليات متعددة القراءة من كائن أو الكتابة إليه في نفس الوقت.
تقدم هذه المقالة مناقشة حول تغيير الكائن في JavaScript مع أمثلة شفرة ذات صلة حيثما كان ذلك ضروريًا.
أنواع البيانات في JavaScript
تشير أنواع البيانات إلى نوع البيانات التي يمكن أن يحتوي عليها متغير أو كائن. JavaScript يدعم فئتين متميزتين من أنواع البيانات: الأنواع البدائية والأنواع المعرفة من قبل المستخدم أو الأنواع المرجعية.
أنواع البيانات البدائية
في JavaScript، جميع أنواع البيانات البدائية غير قابلة للتغيير بطبيعتها، أي أنه لا يمكنك تعديلها بعد إنشائها. الأعداد، القيم البولينية، السلاسل النصية، الأعداد الكبيرة، القيم غير المعرفة، القيم الفارغة، الرموز، والكائنات هي أمثلة على الأنواع البدائية.
أنواع البيانات المعرفة من قبل المستخدم أو الأنواع المرجعية
أنواع البيانات المعرفة من قبل المستخدم أو الأنواع المرجعية هي كائنات تم إنشاؤها باستخدام الأنواع البدائية أو مزيج من الأنواع البدائية وأنواع المعرفة من قبل المستخدم. الأمثلة الشائعة على الأنواع المعرفة من قبل المستخدم أو الأنواع المرجعية هي الكائنات والمصفوفات.
كيف يتم تعيين المتغيرات وإعادة تعيينها في JavaScript
عندما تُسند متغير نوع بدائي إلى متغير بدائي، يحتوي المتغيران على قيم مماثلة، ولكنهما مخزنان في مواقع تخزين مختلفة. على سبيل المثال، نفترض أن لديك متغيرين varA
و varB
وتُسند قيمة متغير إلى آخر بالطريقة التالية:
var varA = 100;
var varB = varA;
console.log(varB);
عند تنفيذ القطعة السابقة من الكود، سيتم عرض الرقم 100 على وحدة التحكم. الآن، قم بتغيير قيمة أحد المتغيرين (مثلاً varB
) كما يظهر هنا.
var varA = 100;
var varB = varA;
varB = 500;
console.log(varA);
لاحظ كيف تم تغيير قيمة المتغير varB
إلى 500. عند طباعة قيمة varA
، ستظل القيمة 100. هذا يحدث لأن هذه المتغيرات varA
و varB
مخزنة في مواقع ذاكرة مختلفة. لذلك، إذا قمت بتغيير أيًا منهما، فإن القيمة الجديدة أو المُغيرة لن تنعكس على المتغيرات الأخرى.
ما هي تحويلات الكائن في جافا سكريبت؟
في جافا سكريبت، يمكن أن ينتمي نوع البيانات للكائن إلى أي من فئتين: بدائي أو غير بدائي. بينما الأنواع البدائية لا تتغير، أي أنه لا يمكنك تغييرها بعد إنشائها، يمكنك تعديل أنواع البيانات غير البدائية، أي الكائنات والمصفوفات. الكائنات تسمح دائمًا بتغيير قيمها. لذا، يمكنك تغيير حالة الحقول لنوع قابل للتغيير دون إنشاء نسخة جديدة.
تحويلات الكائن يمكن أن تخلق عدة مشاكل، مثل ما يلي:
- يمكن أن تؤدي الكائنات المُحوَّلة في كثير من الأحيان إلى حالات منافسة بسبب مشاكل التزامن وأمان الخيوط
- التحول يمكن أن يقدم تعقيدات في الشيفرة المصدرية بسبب قضايا التنبؤ وأمان الخيوط
- التحول غالبًا ما يؤدي إلى وجود علل يمكن أن تكون صعبة التحديد في شيفرة مصدر التطبيق
- التحول يجعل اختبار الشيفرة وتصحيح الأخطاء أمرًا صعبًا لأن تتبع الشيفرة التي تستفيد من التحول يصبح تحديًا
أمثلة على الشيفرة توضح تحول الكائن
يمكن أن يحدث تحول الكائن في أي من السيناريوهات التالية:
- إضافة، تحرير، أو إزالة الخصائص
- استخدام الأساليب التي يمكن أن تظهر تحولًا
عند تعديل خصائص كائن، سواء مباشرة أو غير مباشرة، فإنك في الأساس تقوم بتحويل الكائن. يوضح مقتطف الشيفرة التالي كيف يمكنك تحويل كائن عن طريق تغيير خاصيته.
const author = { id: 1, name: "Joydip Kanjilal"};
author.id = 2; author.city = "Hyderabad, INDIA";
console.log(author);
في قطعة الشيفرة السابقة، ننشئ كائنًا يسمى الكاتب يحتوي على خاصيتين، وهما، id
و name
. بينما تُستخدم الخاصية id
لتخزين id
لسجل الكاتب، تقوم الخاصية name
بتخزين اسم الكاتب. لاحظ كيف نقوم بتحويل كائن الكاتب عن طريق تغيير القيمة المتعلقة بخاصية id
. بعد ذلك، نضيف خاصية جديدة، تسمى city، إلى كائن الكاتب ونعين قيمة للخاصية.
عند تشغيل قطعة الشيفرة السابقة، سيتم عرض الخصائص وقيمها لكائن الكاتب كما هو موضح أدناه:
{ name: 'Joydip Kanjilal', city: 'Hyderabad, INDIA' }
عند تمرير كائن إلى دالة أو تعيينه إلى متغير في جافا سكريبت، فأنت تمرر بالأساس الإشارة إلى الكائن وليس نسخة منه. وهذا يعني أن أي تغيير تقوم به على الكائن الجديد الذي تم تمريره كمعلمة للدالة أو تعيينه إلى المتغير سينعكس على جميع الإشارات للكائن الفعلي.
ننظر في الشيفرة التالية التي توضح كيف يمكنك إنشاء كائن في جافا سكريبت ثم تعيينه إلى متغير.
const objA = { id: 1, name: 'Joydip Kanjilal',
city: 'Hyderabad, INDIA', pincode: 500089 }
const objB = objA;
objB.pincode = 500034;
console.log(objA);
في الشيفرة السابقة، يتم تعيين الكائن objA
إلى objB
، ويتم تغيير قيمة خاصية pincode للكائن objA
، أي يتم تحويل الكائن objA
. عند تنفيذ البرنامج، ستعرض البيانات التالية.
{ id: 1, name: 'Joydip Kanjilal', city: 'Hyderabad, INDIA', pincode: 500034 }
يرجى ملاحظة أن قيمة خاصية pincode قد تم تغييرها.
منع تحويل الكائن في جافا سكريبت
في جافا سكريبت، يمكنك منع التحويل بعدة طرق، مثل ما يلي:
- استخدام نسخ الكائن باستخدام طريقة
Object.assign()
أو عامل الانتشار (…) - استخدام طريقة
Object.seal()
لمنع إضافة أو حذف الخصائص من كائن - استخدام طريقة
Object.freeze()
لمنع إضافة، تحرير، أو حذف الخصائص من كائن
استخدام النسخ
راجع الشيفرة التالية التي توضح كيف يمكنك نسخ كائن في جافا سكريبت باستخدام عامل الانتشار.
let originalObj = { x: 10, y: 100 }; let clonedObj = { originalObj };
هنا، اسم الكائن المستنسخ هو clonedObj
، وهو مطابق للكائن الأصلي المسمى originalObj
. لذا، إذا عرضت قيم الخاصيتين لهذين الكائنين، ستكون النتائج متطابقة.
الآن، قم بتغيير قيمة إحدى الخصائص للكائن المستنسخ المسمى clonedObj
إلى القيمة المرغوبة، كما هو موضح في الكود التالي.
clonedObj.x = 50;
الآن، اكتب الكود التالي لعرض قيمة الخاصية المسماة x
المتعلقة بالكائنين originalObj
و clonedObj
.
console.log(originalObj.x);
console.log(clonedObj.x);
عند تشغيل البرنامج، ستلاحظ أن قيمة الخاصية x
في الكائن الأصلي لم تتغير. سيتم عرض القيم على وحدة التحكم كما هو موضح أدناه:
10
50
استخدام طريقة Object.freeze()
تستطيع طريقة Object.freeze()
جعل كائن لا يمكن تغييره عن طريق منع أي تعديل على أي من خصائصه.
const author = { id: 1, name: "Joydip Kanjilal",
city: "Hyderabad", state: "Telengana",
country: "India", pincode: 500089};
Object.freeze(author);
author.city = "Bangalore";
author.state = "Karnataka";
author.pincode = 560010;
console.log(author);
عند تنفيذ الكود السابق، ستكون النتائج مماثلة لهذا:
{
id: 1,
name: 'Joydip Kanjilal',
city: 'Hyderabad',
state: 'Telangana',
country: 'India',
pincode: 500089
}
كما يمكنك رؤية من النتائج، حتى إذا قمت بتعيين قيم للخصائص city و state، و pincode، لا يوجد تأثير. لذا، لم يتم إجراء أي تغييرات على البيانات الواردة في أي من الخصائص للكائن.
استخدام طريقة Object.seal()
يمكنك أيضًا استخدام طريقة Object.seal()
لمنع تحويل الكائن في جافا سكريبت. تمكنك هذه الطريقة من تعديل قيم الخصائص الحالية، ولكن لا يمكنك تعديل أو حذف أي من خصائص الكائن. يوضح المثال الكودي التالي هذا:
const author = { id: 1, name: "Joydip Kanjilal",
city: "Hyderabad", state: "Telangana",
country: "India", pincode: 500089};
Object.seal(author);
author.city = "Bangalore";
author.state = "Karnataka";
author.pincode = 560005;
author.booksauthored = 3;
console.log(author);
في مقتطف الشيفرة السابق، سيُسمح بتعديل خصائص الكائن المسمى بالمؤلف، لكن لن يُسمح بإضافة أو حذف خصائص الكائن. عند تشغيل البرنامج، ستظهر قيم الخصائص المعدلة في النتيجة، ولكن البيانات التي تقوم بإضافة أو حذف الخصائص تُتجاهل. إليك كيف يبدو الإخراج على واجهة الطرفية:
{
id: 1,
name: 'Joydip Kanjilal',
city: 'Bangalore',
state: 'Karnataka',
country: 'India',
pincode: 560005
}
باستخدام طريقة Object.defineProperty()
يمكنك أيضًا استغلال طريقة Object.defineProperty() في JavaScript للتحكم في قابلية تغيير خصائص كائن بشكل فردي. يوضح مقتطف الشيفرة التالي كيف يمكنك استخدام هذه الطريقة لمنع تعديل القيمة الموجودة في خاصية تم تقييدها من التغير.
const author = { id: 1, name: "Joydip Kanjilal"};
Object.defineProperty(author, "booksauthored",
{
value: 3,
writable: false,
});
author.booksauthored = 5;
console.log(author.booksauthored);
عند تنفيذ قطعة الشيفرة السابقة، سترى أن الرقم 3 يتم عرضه على واجهة الطرفية.
نقاط رئيسية
- يصنف JavaScript أنواع الكائنات إلى فئتين متميزتين: الأساسيات (قابلة للتغيير) والكائنات (غير قابلة للتغيير).
- مصطلح تحوير الكائن يشير إلى العمليات التي تقوم بتعديل أو تغيير كائن بعد إنشائه.
- بينما لا يمكن تغيير القيم الأساسية مثل الرقم، وما إلى ذلك، يمكنك دائمًا تغيير الكائنات بعد إنشائها.
- نظرًا لأن السلاسل في JavaScript غير قابلة للتغيير، فلا يمكنك تعديلها بمجرد إنشائها.
- على الرغم من أن التحوير بحد ذاته ليس بالأمر السيء، يجب إدارته بعناية لتقليل الأخطاء في تطبيقاتك.
- يمكنك تقليل أو القضاء على التحوير في JavaScript عن طريق اتباع الممارسات الموصى بها واستغلال هياكل البيانات غير القابلة للتغيير.
Source:
https://dzone.com/articles/an-introduction-to-object-mutation-in-javascript