عبدالفتاح الصلوي

ما لفرق بين تمرير المتغيرات بالمرجع والقيمة في JavaScript ؟

كتبها : عبدالفتاح الصلوي / في رصيف : جافا سكربت

ما لفرق بين تمرير المتغيرات بالمرجع والقيمة في  JavaScript ؟


عند العمل مع جافا سكريبت، من الضروري فهم الاختلاف بين المرج والقيمة. هذا المفهوم الأساسي يلعب دورًا هاماً في كيفية تخزين المتغيرات والوصول إليها في جافا سكريبت. في هذا المقال، سنستكشف تفاصيل الإشارة والقيمة، ونستكشف تأثيراتها على شفرتك.

مبدئيا عندما نتحدث عن أنواع المتغيرات الأساسية  (البدائية) فاننا نقصد بذلك المتغيرات من نوع ( رقم integer، نص string ، قيمة منطقية boolean).
على الأغلب كل متغير يتم تعريفه في js يعتبر كائن عدى الانواع الأساسية.

مالمقصود بالمرجع Reference:

في جافا سكريبت، يشير المرجع إلى عنوان الكائن في الذاكرة. عند تعريف  متغير متغير من نوع كائن، يخزن المتغير إشارة إلى هذا الكائن بدلاً من الكائن نفسه. هذا يعني أن أي تغييرات تتم على الكائن ستنعكس على جميع المتغيرات التي تشير إليه.

لنأخذ مثالًا:

```javascript
let person1 = { name: "John", age: 25 };
let person2 = person1;
person2.age = 30;
console.log(person1.age); // النتيجة: 30
```

في هذا المثال، يشير `person1` و `person2` إلى نفس الكائن في الذاكرة. عندما نقوم بتحديث خاصية `age` في `person2`، فإنه يؤثر أيضًا على `person1` لأنهما يشتركان في نفس المرجع.

ما المقصود بالقيمة value:


من ناحية أخرى، تشير القيمة إلى البيانات الفعلية المخزنة في المتغير. عند تعيين متغير لنوع بدائي (مثل العدد integer، السلسلة النصيةstring ، القيمة المنطقية boolean)، يحتوي المتغير على القيمة نفسها بدلاً من عنوان المتغير في الذاكرة.

لنأخذ المثال التالي:

```javascript
let num1 = 5;
let num2 = num1;
num2 = 10;
console.log(num1); // النتيجة: 5
```


في هذه الحالة، يحتفظ `num1` و `num2` بقيمهما بشكل مستقل. عند تحديث `num2`، فإنه لا يؤثر على قيمة `num1` لأنهما متغيران منفصلان بقيم متميزة.

تمرير وسائط الدوال:

تسمح JavaScript بتمرير وسائط الدالة بطريقتين - بالقيمة وبالمرجع. وهنا يصبح فهم الاختلاف بين المرجع والقيمة مهمًا بشكل خاص .
عند تمرير متغير ذو قيمة بدائية كوسيط لدالة، تستلم الدالة نسخة من القيمة. أي تعديلات تتم داخل الدالة لا تؤثر على القيمة الأصلية.

```javascript
function updateNumber(num) {
  num = 10;
}
let myNumber = 5;
updateNumber(myNumber);
console.log(myNumber); // النتيجة: 5
```


في هذا المثال، تأخذ دالة `updateNumber` نسخة من `myNumber` وتقوم بتعديلها داخل نطاق الدالة. ومع ذلك، فإن القيمة الأصلية لـ `myNumber` تبقى دون تغيير.

على العكس من ذلك، عند تمرير كائن كوسيط لدالة، تستلم الدالة مرجع إلى الكائن. أي تعديلات تتم داخل الدالة ستؤثر على الكائن الأصلي.
فالكائنات والمصفوفات يتم تمريرها بالمرجع. وعند تمريرها إلى دالة، يتم نسخ المرجع - وليس القيمة الفعلية. لذا فأي تغييرات تتم على الكائن/المصفوفة داخل الدالة ستؤثر على القيم الأصلية حيث يشير كلاهما إلى نفس المرجع في الذاكرة.

let obj = {a: 1};
function changeObj(obj) {
  obj.a = 10;
}
changeObj(obj);
console.log(obj); // يعرض {a: 10}
```

مثال اخر

```javascript
function updatePerson(person) {
  person.age = 30;
}
let myPerson = { name: "John", age: 25 };
updatePerson(myPerson);
console.log(myPerson.age); // النتيجة: 30
```


في هذا المثال، تقوم دالة `updatePerson` بتعديل خاصية `age` في كائن `myPerson`. نظرًا لأن الدالة تستلم إشارة إلى الكائن، فإن التغييرات تنعكس خارج نطاق الدالة.

تمرير ونسخ قيم متغير من نوع (كائن /مصفوفة) بدلا من المرجع


لتمرير كائن/مصفوفة بالقيمة، نحتاج إلى إنشاء نسخة أولاً قبل التمرير.  هناك طرق شائعة في جافا سكريبت منها:

- استخدم Object.assign() لعمل نسخ سطحي shallow copy :

```js
let objCopy = Object.assign({}, obj);
```

- استخدام صيغة spread syntex  لإنشاء نسخة من قيم الكائن او المصفوفة، بكتابة ثلاث نقاط  قبل اسم المتغير عند الاسناد الى متغير  [...] او التمرير الى دالة (arr...).   shallow  copy . مثال :

```js
let arrCopy = [...arr];
```

- للنسخ العميق، استخدم مكتبة مثل lodash's _.cloneDeep().

هناك طريقة اخرى يستخدمها بعض المطورين مثل تحويل القيم الى نص عن طريق دالة JSON.stringfy() ومن ثم اعادة تحويلها الى كائن json.

الخلاصة:

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


علامات ذات صلة :