404 Not Found

404 Not Found


nginx

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

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

ما هي المتغيرات

تخيل صفًا من الصناديق المسماة: واحد اسمه "الاسم" يحتوي "أحمد"، وآخر اسمه "العمر" يحتوي 25. المحتوى يمكن أن يتغير، لكن الاسم يبقى كما هو — هذا هو المتغير.

في JS، تنشئ المتغيرات باستخدام كلمات الإعلان (var / let / const) وتعيين القيم بعلامة يساوي:

HTML
<script>
var name = "أحمد";
let age = 25;
const PI = 3.14;
</script>

مشاكل var

كان var هو الطريقة الوحيدة لإعلان المتغيرات قبل ES6. له سلوكان يسببان صداعًا:

  1. نقطة الدالة — متغير مُعلن بـ var داخل كتلة if أو for يمكن الوصول إليه من الخارج، وهو أمر غير منطقي
  2. الرفع — إعلانات var "مرفوعة" إلى أعلى نطاقها، لكن التعيينات لا تُرفع. يمكنك استخدام متغير قبل إعلانه (قيمته ستكون undefined) بدون أخطاء، مما يؤدي إلى أخطاء خفية

هذان السلوكان يجعلان var أرضًا خصبة للأخطاء. في JS الحديث، تم استبدال var إلى حد كبير بـ let وconst.

let — نطاق الكتلة، الخيار الافتراضي الموصى به

تم تقديم let في ES6 (2015) ويصلح كلتا المشكلتين في var:

في التطوير اليومي، استخدم let للمتغيرات التي تحتاج إلى إعادة تعيين.

let — ثوابت، لا يمكن إعادة تعيينها

const لديه أيضًا نطاق الكتلة، لكن يجب تعيينه عند الإعلان ولا يمكن إعادة تعيينه لاحقًا.

ملاحظة: const يقيد "إعادة التعيين"، وليس "التغيير". إذا كان const يحتوي على كائن أو مصفوفة، يمكنك تعديل خصائص الكائن أو عناصر المصفوفة — فقط لا يمكن للمتغير أن يشير إلى كائن مختلف.

استخدم const افتراضيًا؛ انتقل إلى let عندما تحتاج إلى إعادة تعيين — هذه هي أفضل ممارسة.

قواعد تسمية المتغيرات

إعلان متغيرات متعددة

يمكنك إعلان متغيرات متعددة دفعة واحدة، مفصولة بفواصل:

HTML
<script>
let a = 1, b = 2, c = 3;
</script>

ومع ذلك، للقراءة، يُفضل متغير واحد لكل سطر.

مثال: رفع var ونقطة الدالة

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>متغيرات JS - مشاكل var</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .warn { background: #fff3e0; padding: 12px; border-radius: 8px; color: #E65100; border-left: 4px solid #FF9800; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #FF9800; margin: 6px; }
    button:hover { background: #F57C00; }
  </style>
</head>
<body>
  <h2>عرض مشاكل var</h2>
  <p class="warn">⚠️ var لديه مشاكل في الرفع ونقطة الدالة — تجنبه في الكود الحديث</p>
  <button id="hoistBtn">عرض: الرفع</button>
  <button id="scopeBtn">عرض: تسرّب النطاق</button>
  <div class="result" id="output">انقر على زر لرؤية النتائج</div>
  <script>
    document.getElementById("hoistBtn").onclick = function() {
      var output = "";
      output += "الوصول إلى x قبل إعلان var: x = " + typeof x + "\n";
      var x = 10;
      output += "بعد الإعلان: x = " + x + "\n\n";
      output += "👆 الرفع يسبب عدم وجود خطأ قبل الإعلان، لكن القيمة undefined\n";
      output += "هذا يمكن أن يسبب بسهولة أخطاء في المشاريع الكبيرة!";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("scopeBtn").onclick = function() {
      var output = "";
      for (var i = 0; i < 3; i++) {
        // var i يتسرب خارج الحلقة
      }
      output += "بعد الحلقة، i = " + i + "\n\n";
      output += "👆 var i تسربت خارج الحلقة!\n";
      output += "مع let i، لن يمكن الوصول إليها من الخارج";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: نطاق كتلة let

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>متغيرات JS - نطاق كتلة let</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .good { background: #e8f5e9; padding: 12px; border-radius: 8px; color: #2E7D32; border-left: 4px solid #4CAF50; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #4CAF50; margin: 6px; }
    button:hover { background: #388E3C; }
  </style>
</head>
<body>
  <h2>عرض نطاق كتلة let</h2>
  <p class="good">✅ let لديه نطاق كتلة — غير قابل للوصول خارج {}، وهو أكثر أمانًا</p>
  <button id="letScopeBtn">عرض: نطاق كتلة let</button>
  <button id="letLoopBtn">عرض: let في الحلقات</button>
  <div class="result" id="output">انقر على زر لرؤية النتائج</div>
  <script>
    document.getElementById("letScopeBtn").onclick = function() {
      let output = "اختبار نطاق الكتلة:\n";
      let x = 100;
      output += "x الخارجي = " + x + "\n";
      {
        let x = 200;
        output += "x الداخلي = " + x + "\n";
      }
      output += "بعد الكتلة، x = " + x + "\n\n";
      output += "👆 x الداخلي والخارجي مستقلان عن بعضهما البعض";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("letLoopBtn").onclick = function() {
      let output = "let في الحلقات:\n";
      for (let i = 0; i < 3; i++) {
        output += "داخل الحلقة، i = " + i + "\n";
      }
      output += "\n";
      try {
        output += "خارج الحلقة، i = " + i;
      } catch(e) {
        output += "الوصول إلى i خارج الحلقة → خطأ: " + e.message;
      }
      output += "\n\n👆 let i محصورة في الحلقة ولا تتسرب خارجها";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: ثوابت const

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>متغيرات JS - ثوابت const</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .tip { background: #e3f2fd; padding: 12px; border-radius: 8px; color: #1565C0; border-left: 4px solid #2196F3; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; margin: 6px; }
    #constBtn { background: #9C27B0; }
    #objectBtn { background: #2196F3; }
  </style>
</head>
<body>
  <h2>عرض ثوابت const</h2>
  <p class="tip">💡 const لا يمكن إعادة تعيينه، لكن يمكن تعديل خصائص الكائن/المصفوفة وعناصرها</p>
  <button id="constBtn">عرض: خطأ إعادة تعيين const</button>
  <button id="objectBtn">عرض: تعديل كائن const</button>
  <div class="result" id="output">انقر على زر لرؤية النتائج</div>
  <script>
    document.getElementById("constBtn").onclick = function() {
      const PI = 3.14159;
      let output = "const PI = " + PI + "\n\n";
      output += "محاولة إعادة تعيين PI = 3.14:\n";
      try {
        PI = 3.14;
      } catch(e) {
        output += "❌ خطأ: " + e.message;
      }
      output += "\n\n👆 بمجرد التعيين، لا يمكن تغيير المتغير const";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("objectBtn").onclick = function() {
      const person = { name: "أحمد", age: 25 };
      let output = "const person = " + JSON.stringify(person) + "\n\n";
      output += "تعديل person.age = 26:\n";
      person.age = 26;
      output += "person = " + JSON.stringify(person) + "\n\n";
      output += "إضافة person.city = 'القاهرة':\n";
      person.city = "القاهرة";
      output += "person = " + JSON.stringify(person) + "\n\n";
      output += "👆 const يقفل مرجع المتغير، وليس محتوى الكائن\n";
      output += "مثل صندوق به مسمار مقفل — ما بداخله لا يزال يمكن تغييره";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: مقارنة var / let / const

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>متغيرات JS - مقارنة الإعلانات الثلاثة</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 60px auto; }
    table { width: 100%; border-collapse: collapse; margin: 16px 0; }
    th, td { padding: 10px; text-align: center; border: 1px solid #ddd; }
    th { background: #2196F3; color: #fff; }
    .bad { color: #f44336; }
    .good { color: #4CAF50; font-weight: bold; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #e91e63; }
    #result { margin-top: 12px; padding: 16px; background: #f5f5f5; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; }
  </style>
</head>
<body>
  <h2>مقارنة var / let / const</h2>
  <table>
    <tr><th>الميزة</th><th>var</th><th>let</th><th>const</th></tr>
    <tr><td>النطاق</td><td class="bad">الدالة</td><td class="good">الكتلة</td><td class="good">الكتلة</td></tr>
    <tr><td>الرفع</td><td class="bad">نعم (undefined)</td><td class="good">لا (TDZ)</td><td class="good">لا (TDZ)</td></tr>
    <tr><td>قابلية إعادة التعيين</td><td class="bad">نعم</td><td>نعم</td><td class="bad">لا</td></tr>
    <tr><td>الاستخدام قبل الإعلان</td><td class="bad">لا خطأ</td><td class="good">خطأ</td><td class="good">خطأ</td></tr>
    <tr><td>موصى به</td><td class="bad">تجنب</td><td class="good">موصى به</td><td class="good">مفضل</td></tr>
  </table>
  <button id="testBtn">تشغيل اختبار المقارنة</button>
  <div id="result"></div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var output = "=== اختبار المقارنة ===\n\n";
      output += "[var] نطاق الدالة:\n";
      for (var i = 0; i < 3; i++) {}
      output += "var i خارج الحلقة = " + i + " (تسرب)\n\n";
      output += "[let] نطاق الكتلة:\n";
      for (let j = 0; j < 3; j++) {}
      try {
        output += "let j خارج الحلقة = " + j;
      } catch(e) {
        output += "الوصول إلى let j خارج الحلقة → " + e.message + " (السلوك الصحيح)";
      }
      output += "\n\n[const] لا إعادة تعيين:\n";
      const MAX = 100;
      output += "const MAX = " + MAX + "\n";
      try {
        MAX = 200;
      } catch(e) {
        output += "إعادة التعيين → " + e.message + " (السلوك الصحيح)";
      }
      output += "\n\nالخلاصة: const > let >> var";
      document.getElementById("result").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

📖 ملخص

  1. المتغيرات هي صناديق لتخزين البيانات، تُنشأ بكلمة إعلان + اسم متغير + تعيين
  2. var لديه مشاكل في نطاق الدالة والرفع — تجنبه في JS الحديث
  3. let لديه نطاق الكتلة ولا رفع — استخدمه عندما تحتاج إلى إعادة تعيين
  4. const لديه نطاق الكتلة ولا يمكن إعادة تعيينه — يجب تعيينه عند الإعلان
  5. const يمنع إعادة التعيين، لكن لا يزال يمكن تعديل خصائص الكائن/المصفوفة وعناصرها
  6. الأولوية: const أولاً، let ثانيًا، تجنب var

❓ أسئلة شائعة

س إذا كان بإمكان كائنات const التعديل، ما فائدة const؟
ج const يضمن أن مرجع المتغير لن يتغير — لا يمكنك إعادة تعيين person عن طريق الخطأ إلى كائن مختلف، لكن تعديل خصائص الكائن الحالي مسموح تمامًا. إنه مثل قفل مسمار الصندوق (هذا الصندوق دائمًا "صندوق أحمد")، لكن يمكنك وضع ما تريد بداخله.
س متى يجب استخدام let مقابل const؟
ج قاعدة بسيطة: اسأل نفسك "هل ستتغير هذه القيمة؟" — إذا لا، استخدم const؛ إذا نعم، استخدم let. على سبيل المثال، العدادات تستخدم let، ثوابت التكوين تستخدم const. في الممارسة العملية، ستستخدم const أكثر بكثير من let.
س هل لا يزال بإمكاني استخدام var؟
ج تقنيًا نعم، لكن لا يوجد سبب لذلك. let وconst هما ترقيات كاملة لـ var — لا يوجد سenario حيث يكون var مطلوبًا لكن let/const لن يعملا. فهم var في الكود القديم مقبول، لكن استخدم دائمًا let/const في الكود الجديد.

📝 تمارين

  1. أساسي: أعلن ثابت SITE_NAME باسمك باستخدام const، ومتغير visitCount مضبوط على 0 باستخدام let، ثم اعرض كلا القيمتين على الصفحة.
  2. متوسط: أنشئ صفحة بها زر يحاكي "عداد الزيارات" — كل نقرة تزيد visitCount بمقدار 1 وتعرض القيمة الحالية. لاحظ كيف يسمح let بإعادة التعيين بينما const لا.
  3. تحدي: أنشئ صفحة بها كائن طالب const { name: "أحمد", scores: [80, 90, 75] }. ثم أضف درجة جديدة 85، احسب المتوسط، وغيّر الاسم إلى "سارة" — كل هذا بدون إعادة تعيين const، مما يثبت أنه يمكن تعديل محتوى الكائن.
100%