متغيرات جافاسكريبت
المتغيرات هي صناديق لتخزين البيانات — تضع على كل صندوق اسمًا، ثم تضع البيانات فيه، أو تخرجها، أو تستبدلها في أي وقت.
ما هي المتغيرات
تخيل صفًا من الصناديق المسماة: واحد اسمه "الاسم" يحتوي "أحمد"، وآخر اسمه "العمر" يحتوي 25. المحتوى يمكن أن يتغير، لكن الاسم يبقى كما هو — هذا هو المتغير.
في JS، تنشئ المتغيرات باستخدام كلمات الإعلان (var / let / const) وتعيين القيم بعلامة يساوي:
<script>
var name = "أحمد";
let age = 25;
const PI = 3.14;
</script>
مشاكل var
كان var هو الطريقة الوحيدة لإعلان المتغيرات قبل ES6. له سلوكان يسببان صداعًا:
- نقطة الدالة — متغير مُعلن بـ
varداخل كتلةifأوforيمكن الوصول إليه من الخارج، وهو أمر غير منطقي - الرفع — إعلانات
var"مرفوعة" إلى أعلى نطاقها، لكن التعيينات لا تُرفع. يمكنك استخدام متغير قبل إعلانه (قيمته ستكونundefined) بدون أخطاء، مما يؤدي إلى أخطاء خفية
هذان السلوكان يجعلان var أرضًا خصبة للأخطاء. في JS الحديث، تم استبدال var إلى حد كبير بـ let وconst.
let — نطاق الكتلة، الخيار الافتراضي الموصى به
تم تقديم let في ES6 (2015) ويصلح كلتا المشكلتين في var:
- نقطة الكتلة — يمكن الوصول إليه فقط داخل
{}، لا يمكن الوصول إليه خارج الكتلة - لا رفع — استخدام متغير قبل إعلانه يُلقي خطأ (المنطقة الزمنية الميتة)
في التطوير اليومي، استخدم let للمتغيرات التي تحتاج إلى إعادة تعيين.
let — ثوابت، لا يمكن إعادة تعيينها
const لديه أيضًا نطاق الكتلة، لكن يجب تعيينه عند الإعلان ولا يمكن إعادة تعيينه لاحقًا.
ملاحظة: const يقيد "إعادة التعيين"، وليس "التغيير". إذا كان const يحتوي على كائن أو مصفوفة، يمكنك تعديل خصائص الكائن أو عناصر المصفوفة — فقط لا يمكن للمتغير أن يشير إلى كائن مختلف.
استخدم const افتراضيًا؛ انتقل إلى let عندما تحتاج إلى إعادة تعيين — هذه هي أفضل ممارسة.
قواعد تسمية المتغيرات
- يجب أن يبدأ بحرف، شرطة سفلية
_، أو علامة الدولار$ - الأحرف اللاحقة يمكن أن تكون أحرفًا، أرقامًا، شرطات سفلية، أو علامات دولار
- لا يمكن أن يبدأ برقم
- لا يمكن استخدام كلمات مفتاحية في JS (
var،let،function، إلخ) - camelCase موصى به:
firstName،totalPrice
إعلان متغيرات متعددة
يمكنك إعلان متغيرات متعددة دفعة واحدة، مفصولة بفواصل:
<script>
let a = 1, b = 2, c = 3;
</script>
ومع ذلك، للقراءة، يُفضل متغير واحد لكل سطر.
مثال: رفع var ونقطة الدالة
<!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
<!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
<!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
<!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>
📖 ملخص
- المتغيرات هي صناديق لتخزين البيانات، تُنشأ بكلمة إعلان + اسم متغير + تعيين
varلديه مشاكل في نطاق الدالة والرفع — تجنبه في JS الحديثletلديه نطاق الكتلة ولا رفع — استخدمه عندما تحتاج إلى إعادة تعيينconstلديه نطاق الكتلة ولا يمكن إعادة تعيينه — يجب تعيينه عند الإعلانconstيمنع إعادة التعيين، لكن لا يزال يمكن تعديل خصائص الكائن/المصفوفة وعناصرها- الأولوية: const أولاً، let ثانيًا، تجنب var
❓ أسئلة شائعة
person عن طريق الخطأ إلى كائن مختلف، لكن تعديل خصائص الكائن الحالي مسموح تمامًا. إنه مثل قفل مسمار الصندوق (هذا الصندوق دائمًا "صندوق أحمد")، لكن يمكنك وضع ما تريد بداخله.📝 تمارين
- أساسي: أعلن ثابت
SITE_NAMEباسمك باستخدامconst، ومتغيرvisitCountمضبوط على 0 باستخدامlet، ثم اعرض كلا القيمتين على الصفحة. - متوسط: أنشئ صفحة بها زر يحاكي "عداد الزيارات" — كل نقرة تزيد
visitCountبمقدار 1 وتعرض القيمة الحالية. لاحظ كيف يسمحletبإعادة التعيين بينماconstلا. - تحدي: أنشئ صفحة بها كائن طالب
const{ name: "أحمد", scores: [80, 90, 75] }. ثم أضف درجة جديدة 85، احسب المتوسط، وغيّر الاسم إلى "سارة" — كل هذا بدون إعادة تعيين const، مما يثبت أنه يمكن تعديل محتوى الكائن.



