المتغيرات في جافا سكربت



المتغيرات (Variables) var و let و const

تعتبر المتغيرات (Variables) هي حجر الأساس الأول في أي لغة برمجة، وليست حصراً على JavaScript. تخيل معي أنك تنتقل إلى منزل جديد؛ ستحتاج بالتأكيد إلى “صناديق” لتضع فيها أغراضك، وستقوم بكتابة “ملصق” على كل صندوق لتعرف ما بداخله (مثلاً: صندوق الكتب، صندوق الملابس). في البرمجة، المتغيرات هي هذه “الصناديق”، والبيانات هي “الأغراض”، واسم المتغير هو “الملصق”.

في JavaScript، تطور الأمر عبر الزمن. قديماً كان لدينا نوع واحد فقط من الصناديق (`var`)، ولكن ظهرت به مشاكل كثيرة، مما دفع المطورين لابتكار صناديق أكثر ذكاءً وأماناً (`let` و `const`) في تحديث عام 2015 (ES6). في هذا الدرس، سنشرح بالتفصيل الممل الفرق بين الثلاثة، ولماذا يجب عليك ترك القديم والتمسك بالجديد.



المتغير القديم (var) ومشاكله

قبل عام 2015، لم يكن هناك سوى var لتعريف المتغيرات. ورغم أنه لا يزال يعمل حتى اليوم، إلا أنه يعتبر “مصدراً للمشاكل” في المشاريع الكبيرة بسبب طريقته الغريبة في التعامل مع الذاكرة والنطاق.

المشكلة الأولى: النطاق الوظيفي (Function Scope)

المتغير المعرف بـ var يحترم فقط حدود “الدالة” (Function). هذا يعني أنه إذا قمت بتعريفه داخل جملة شرطية if أو حلقة تكرار for، فإنه “سيتسرب” خارجها ويصبح متاحاً في كامل المكان! وهذا يسبب تداخلات خطيرة في البيانات.

تخيل أنك تضع صندوقاً داخل غرفة مغلقة (الدالة)، هنا لا يمكن لأحد خارج الغرفة رؤيته. لكن إذا وضعته داخل “خيمة” شفافة (مثل if block) داخل الغرفة، فسيراه الجميع. هذا هو عيب var، لا يحترم الخيام (Blocks)، يحترم فقط الغرف المغلقة (Functions).

مثال: تسرب var خارج الـ Block

// مثال يوضح عيب var
var x = 10;

if (true) {
    // تخيل أننا نريد متغير مؤقت داخل الـ if فقط
    var x = 20; 
    console.log("داخل الشرط:", x); // النتيجة: 20
}

// المفاجأة! لقد تغير المتغير الأصلي خارج الشرط أيضاً
console.log("خارج الشرط:", x); // النتيجة: 20 (وليس 10 كما نتوقع!)

المشكلة الثانية: إعادة الإعلان (Redeclaration)

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

مثال: كارثة إعادة الإعلان

var name = "Ahmed";
var name = "Sara"; // لا يوجد خطأ! (No Error)

console.log(name); // سيطبع Sara
// تخيل لو كان الكود 1000 سطر، لن تكتشف أن Ahmed ضاعت

اختر – لماذا يُعتبر استخدام var خطيراً في المشاريع الكبيرة؟
(أ) لأنه لا يعمل على المتصفحات القديمة. (ب) لأنه يسمح بتسرب المتغيرات خارج الـ Blocks (مثل if و for) ويسمح بإعادة تعريف المتغير دون خطأ. (ج) لأنه لا يقبل تخزين النصوص. (د) لأنه أبطأ في التنفيذ من let.

الإجابة: (ب) لأنه يسمح بتسرب المتغيرات خارج الـ Blocks ويسمح بإعادة تعريف المتغير دون خطأ. (وهذا هو السبب الرئيسي لاستبداله).

المتغير الحديث والمرن (let)

جاء let ليكون المنقذ. هو البديل المباشر لـ var ولكنه “منضبط”. إذا كان var متغيراً فوضوياً، فإن let متغير يحترم القوانين والحدود.

الميزة الأهم: النطاق الكتلي (Block Scope)

الـ Block هو أي كود محصور بين قوسين متعرجين { ... }. هذا يشمل الـ Functions، الـ Loops، وجمل الـ If.

عندما تعرف متغيراً باستخدام let داخل { }، فإنه يعيش ويموت داخل هذين القوسين. لا يمكن لأي كود خارجهما أن يراه أو يعبث به. هذا يوفر حماية هائلة لبياناتك ويمنع التداخلات غير المقصودة.

مثال: let يحترم الحدود

let y = 10; // متغير عالمي

if (true) {
    let y = 50; // هذا متغير جديد كلياً، يعيش داخل الـ if فقط
    console.log("داخل البلوك:", y); // النتيجة: 50
}

console.log("خارج البلوك:", y); // النتيجة: 10 (لم يتأثر أبداً!)
// هذا هو السلوك الصحيح والمنطقي

منع إعادة الإعلان

على عكس var، إذا حاولت تعريف متغير بنفس الاسم مرتين باستخدام let في نفس النطاق، سيقوم JavaScript بإيقافك فوراً وإظهار رسالة خطأ (SyntaxError). هذا يحميك من الكتابة فوق بياناتك بالخطأ.

ملاحظة هامة: يمكنك “تحديث” قيمة let (Reassign)، ولكن لا يمكنك “إعادة تعريفه” (Redeclare).

مثال: التحديث مقابل إعادة التعريف

let user = "Ali";
user = "Mohamed"; // مسموح (تحديث القيمة)

// let user = "Samy"; 
// خطأ !! ممنوع إعادة التعريف (SyntaxError)

اختر – ماذا سيحدث إذا قمت بكتابة الكود التالي: let x = 5; let x = 10;؟
(أ) ستصبح قيمة x تساوي 10. (ب) ستصبح قيمة x تساوي 15. (ج) سيعطي المتصفح خطأ (SyntaxError) لأن الاسم مستخدم مسبقاً. (د) سيتم تجاهل السطر الثاني.

الإجابة: (ج) سيعطي المتصفح خطأ (SyntaxError). (لأن let تمنع إعادة تعريف المتغير في نفس النطاق لحمايتك).

الثابت الصارم (const)

كلمة const هي اختصار لـ Constant (ثابت). وهي تشبه let تماماً في خاصية (Block Scope) ومنع إعادة التعريف، ولكنها تضيف شرطاً صارماً جداً: لا يمكن تغيير القيمة بعد تعيينها لأول مرة.

متى نستخدم const؟

القاعدة الذهبية للمبرمجين المحترفين حالياً هي: استخدم const كخيار افتراضي دائماً. لماذا؟ لأن معظم المتغيرات التي نستخدمها لا تحتاج لتغيير قيمتها لاحقاً (مثل رابط قاعدة البيانات، مفتاح API، أو عنصر HTML قمنا بجلبه). استخدام const يخبر أي مبرمج يقرأ الكود بعدك: “هذه القيمة ثابتة ولن تتغير، فلا تقلق بشأنها”.

إذا اكتشفت لاحقاً أنك بحاجة لتغيير القيمة (مثلاً عداد loops)، قم بتحويلها إلى let.

مفهوم “الثبات” الخادع مع الكائنات (Objects)

هذه نقطة متقدمة قليلاً ولكنها ضرورية للفهم. عندما نستخدم const مع الأرقام والنصوص، لا يمكن تغييرها. ولكن عند استخدامها مع الكائنات (Objects) أو المصفوفات (Arrays)، فإن كلمة const تحمي “الصندوق” فقط، ولا تحمي “محتويات الصندوق”.

  • يمكنك تعديل خصائص الكائن (Object Properties).
  • يمكنك إضافة عناصر للمصفوفة (Array).
  • لكن! لا يمكنك استبدال الكائن أو المصفوفة بكائن جديد تماماً.
مثال: الثبات والمرونة في const

const PI = 3.14;
// PI = 3.14159; // خطأ! (TypeError) - لا يمكن تغيير القيم الأساسية

// مع المصفوفات (Arrays)
const colors = ["Red", "Green"];

colors.push("Blue"); // مسموح! (نعدل المحتوى)
console.log(colors); // ["Red", "Green", "Blue"]

// colors = ["Yellow", "Black"]; // خطأ! (لا يمكن استبدال الصندوق بالكامل)

اختر – قمت بتعريف مصفوفة كالتالي: const list = [1, 2];. أي العمليات التالية مسموح بها؟
(أ) list = [1, 2, 3];. (ب) list = [];. (ج) list.push(3);. (د) لا شيء مما سبق، المصفوفة ثابتة تماماً.

الإجابة: (ج) list.push(3);. (لأن const مع الكائنات والمصفوفات تمنع إعادة التعيين “=”، ولكنها تسمح بتعديل المحتويات الداخلية).

مفهوم النطاق (Scope) بالتفصيل

لقد ذكرنا كلمة “نطاق” كثيراً، حان الوقت لتلخيص أنواع النطاق في JavaScript وعلاقتها بالمتغيرات.

1. النطاق العام (Global Scope)

أي متغير يتم تعريفه خارج أي دالة أو Block يعتبر عاماً. يمكن الوصول إليه من أي مكان في ملف الكود. المتغيرات العامة تستهلك الذاكرة طوال فترة فتح الصفحة، واستخدامها بكثرة يعتبر ممارسة سيئة.

2. النطاق الوظيفي (Function Scope)

خاص بالمتغيرات المعرفة بـ var، let، و const داخل دالة (Function). هذه المتغيرات تولد عند استدعاء الدالة وتموت بمجرد انتهاء الدالة. لا يمكن رؤيتها من الخارج.

3. النطاق الكتلي (Block Scope)

ظهر هذا المفهوم مع ES6 (2015). وهو خاص بـ let و const فقط. أي كود بين { } (مثل if, switch, for, while) يعتبر عالماً مستقلاً لهذه المتغيرات.

اختر – المتغير الذي يتم تعريفه بـ let داخل حلقة for loop (مثلاً: for(let i=0; i<5; i++)) ...
(أ) يمكن استخدامه خارج الحلقة بعد انتهائها. (ب) يعتبر متغير global. (ج) يكون مرئياً ومتاحاً فقط داخل جسم الحلقة {}. (د) يصبح const تلقائياً.

الإجابة: (ج) يكون مرئياً ومتاحاً فقط داخل جسم الحلقة {}. (بسبب خاصية Block Scope).

جدول المقارنة ومتى تستخدم كل نوع؟

لتلخيص كل ما سبق في مرجع سريع، إليك هذا الجدول الذي يوضح الفروقات التقنية.

وجه المقارنة var (القديم) let (الحديث) const (الثابت)
النطاق (Scope) Function Scope (داخل الدالة فقط) Block Scope (داخل { } فقط) Block Scope (داخل { } فقط)
إعادة الإعلان (Redeclare) مسموح (وهذا خطير) غير مسموح (يعطي Error) غير مسموح (يعطي Error)
إعادة التعيين (Reassign) مسموح مسموح غير مسموح أبداً
القيمة المبدئية يمكن تركه بدون قيمة (undefined) يمكن تركه بدون قيمة (undefined) يجب إعطاء قيمة فوراً عند التعريف

الخلاصة: ماذا أستخدم؟

اتبع هذه القواعد في كتابة الكود الخاص بك لتصبح مبرمجاً محترفاً:

  • المرتبة الأولى: استخدم const دائماً. اجعلها عادتك. لماذا؟ لأنها تجعل الكود أسهل في القراءة وأقل عرضة للأخطاء.
  • المرتبة الثانية: إذا كنت متأكداً أن قيمة المتغير ستتغير (مثل عداد في حلقة تكرار، أو نتيجة تتبدل)، استخدم let.
  • المرتبة الأخيرة: لا تستخدم var أبداً في المشاريع الجديدة. استخدمها فقط إذا كنت مضطراً للعمل على كود قديم جداً (Legacy Code) مكتوب قبل 2015.

اختر - الترتيب الصحيح للأفضلية في استخدام المتغيرات عند كتابة كود جديد هو:
(أ) var ثم let ثم const. (ب) let لكل شيء. (ج) const كخيار أول، ثم let عند الحاجة للتغيير، وتجنب var. (د) var للأرقام و const للنصوص.

الإجابة: (ج) const كخيار أول، ثم let عند الحاجة للتغيير، وتجنب var. (هذه هي الممارسة القياسية العالمية حالياً).




اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

تابع جديد الوظائف
Scroll to Top