404 Not Found

404 Not Found


nginx

أنواع البيانات في جافاسكريبت

أنواع البيانات تحدد العمليات التي يمكنك تنفيذها — الأرقام تدعم الحسابات، والنصوص تدعم الربط، والقيم المنطقية تدعم الشروط. فهم الأنواع يساعدك على تجنب أكثر فخاخ JS كلاسيكية.

أنواع البيانات في JS

تحتوي جافاسكريبت على 8 أنواع بيانات، مقسمة إلى بدائل وأنواع مرجعية:

بدائل (7 أنواع): String، Number، BigInt، Boolean، Undefined، Null، Symbol

نوع مرجعي (نوع واحد): Object (المصفوفات، الدوال، التواريخ، إلخ كلها أنواع فرعية من Object)

البيانات البديلة تُخزن في ذاكرة المكدس وتُنسخ بالقيمة أثناء التعيين. البيانات من النوع المرجعي تُخزن في ذاكرة الكومة وتُنسخ بالمرجع (العنوان) أثناء التعيين. سيتم تغطية هذا التمييز بالتفصيل في الدروس اللاحقة.

عامل typeof

typeof هو عامل يتحقق من أنواع البيانات ويعيد نصًا:

القيمة نتيجة typeof
"مرحبا" "string"
42 "number"
9007199254740991n "bigint"
true "boolean"
undefined "undefined"
null "object" (خطأ تاريخي)
{ } "object"
function(){} "function"

ملاحظة: typeof null يعيد "object" — هذا خطأ تاريخي من بداية JS لا يمكن إصلاحه (تغييره سيكسر الكود الموجود). فقط تذكره.

فخاخ النص والأرقام

عامل + في JS يخدم غرضين: الجمع العددي وربط النصوص. عندما يكون أحد طرفي + نصًا، يحول JS القيمة الأخرى إلى نص أيضًا:

هذا هو أحد أكثر فخاخ JS كلاسيكية — كل مبتدئ يقع فيه. الحل: استخدم Number() أو parseInt() للتحويل الصريح قبل العمليات الحسابية.

null مقابل undefined

كلاهما يعني "لا قيمة"، لكنهما يختلفان في النية:

فكر فيها بهذه الطريقة: undefined هو منزل جديد بدون أثاث بعد؛ null هو عندما نقلت جميع الأثاث عمدًا.

مثال: typeof مع أنواع مختلفة

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>أنواع البيانات - typeof</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: left; border: 1px solid #ddd; }
    th { background: #2196F3; color: #fff; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #2196F3; }
    #result { margin-top: 12px; padding: 16px; background: #f5f5f5; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; }
  </style>
</head>
<body>
  <h2>عامل typeof</h2>
  <button id="testBtn">تشغيل اختبار typeof</button>
  <div id="result">انقر على الزر لرؤية نتائج typeof</div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var a = "مرحبا";
      var b = 42;
      var c = 9007199254740991n;
      var d = true;
      var e = undefined;
      var f = null;
      var g = {name: "أحمد"};
      var h = [1, 2, 3];
      var i = function(){};
      var output = "";
      output += 'typeof "مرحبا"  → "' + typeof a + '"\n';
      output += "typeof 42       → \"" + typeof b + '"\n';
      output += "typeof 9007199254740991n → \"" + typeof c + '"\n';
      output += "typeof true     → \"" + typeof d + '"\n';
      output += "typeof undefined → \"" + typeof e + '"\n';
      output += "typeof null     → \"" + typeof f + '"  ⚠️ خطأ تاريخي!\n';
      output += "typeof {}       → \"" + typeof g + '"\n';
      output += "typeof []       → \"" + typeof h + '"  (المصفوفات أيضًا كائنات)\n';
      output += 'typeof function → "' + typeof i + '"';
      document.getElementById("result").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: فخاخ النص والأرقام

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>أنواع البيانات - فخ النص مقابل الرقم</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .trap { background: #fff3e0; padding: 12px; border-radius: 8px; color: #E65100; border-left: 4px solid #FF9800; margin: 12px 0; }
    .safe { background: #e8f5e9; padding: 12px; border-radius: 8px; color: #2E7D32; border-left: 4px solid #4CAF50; margin: 12px 0; }
    .row { display: flex; justify-content: space-between; padding: 10px 16px; border-bottom: 1px solid #eee; font-family: Consolas, monospace; }
    .row:last-child { border-bottom: none; }
    .result-box { background: #f5f5f5; border-radius: 8px; margin: 12px 0; overflow: hidden; }
    .label { color: #666; }
    .value { font-weight: bold; }
    .bad { color: #f44336; }
    .good { color: #4CAF50; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #e91e63; }
  </style>
</head>
<body>
  <h2>فخ النص + الرقم</h2>
  <p class="trap">⚠️ عندما يكون هناك نص على أي طرف من +، يقوم JS بالربط بدلاً من الجمع! "5"+3 يعطي "53"، وليس 8</p>
  <button id="trapBtn">تشغيل عرض الفخ</button>
  <div class="result-box" id="trapResult">
    <div class="row"><span class="label">"5" + 3 =</span><span class="value" id="r1">?</span></div>
    <div class="row"><span class="label">5 + 3 =</span><span class="value" id="r2">?</span></div>
    <div class="row"><span class="label">"5" - 3 =</span><span class="value" id="r3">?</span></div>
    <div class="row"><span class="label">"5" * 3 =</span><span class="value" id="r4">?</span></div>
  </div>
  <p class="safe">✅ الحل: استخدم Number() للتحويل الصريح قبل العمليات الحسابية</p>
  <button id="safeBtn" style="background:#4CAF50;">تشغيل النسخة الآمنة</button>
  <div class="result-box" id="safeResult">
    <div class="row"><span class="label">Number("5") + 3 =</span><span class="value" id="s1">?</span></div>
  </div>
  <script>
    document.getElementById("trapBtn").onclick = function() {
      var r1 = "5" + 3;
      var r2 = 5 + 3;
      var r3 = "5" - 3;
      var r4 = "5" * 3;
      document.getElementById("r1").textContent = '"' + r1 + '"';
      document.getElementById("r1").className = "value bad";
      document.getElementById("r2").textContent = r2;
      document.getElementById("r2").className = "value good";
      document.getElementById("r3").textContent = r3;
      document.getElementById("r3").className = "value good";
      document.getElementById("r4").textContent = r4;
      document.getElementById("r4").className = "value good";
    };
    document.getElementById("safeBtn").onclick = function() {
      var s1 = Number("5") + 3;
      document.getElementById("s1").textContent = s1;
      document.getElementById("s1").className = "value good";
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: null مقابل undefined

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>أنواع البيانات - null مقابل undefined</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .card { padding: 16px; border-radius: 8px; margin: 12px 0; }
    .undef { background: #e3f2fd; border-left: 4px solid #2196F3; }
    .nul { background: #f3e5f5; border-left: 4px solid #9C27B0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #9C27B0; margin: 6px; }
  </style>
</head>
<body>
  <h2>null مقابل undefined</h2>
  <div class="card undef">
    <strong>undefined</strong>: متغير تم إعلانه لكن لم يُعيَّن، أو خاصية غير موجودة<br>
    المعنى: "لم تُعطَ قيمة بعد" — مثل منزل جديد بدون أثاث
  </div>
  <div class="card nul">
    <strong>null</strong>: المطور عيّنه صراحة كفارغ<br>
    المعنى: "تم تعيينه عمدًا كلا شيء" — نقلت الأثاث عمدًا
  </div>
  <button id="testBtn">تشغيل اختبار المقارنة</button>
  <div class="result" id="output">انقر على الزر لرؤية النتائج</div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var a;
      var b = null;
      var c = {name: "أحمد"};
      var output = "";
      output += "=== حالات undefined ===\n";
      output += "var a;  → a = " + a + " (undefined)\n";
      output += "typeof a → \"" + typeof a + "\"\n";
      output += "c.age → " + c.age + " (خاصية غير موجودة أيضًا undefined)\n\n";
      output += "=== حالات null ===\n";
      output += "var b = null;  → b = " + b + " (null)\n";
      output += "typeof b → \"" + typeof b + "\"  ⚠️ خطأ تاريخي\n\n";
      output += "=== المقارنة ===\n";
      output += "null == undefined  → " + (null == undefined) + "  (تساوي متساهل)\n";
      output += "null === undefined → " + (null === undefined) + "  (عدم تساوي صارم)\n";
      output += "typeof null  → \"object\"  (خطأ)\n";
      output += "typeof undefined → \"undefined\"  (صحيح)\n\n";
      output += "الخلاصة: null === undefined هو false\n";
      output += "لهما معنيان مختلفان وليسا نفس القيمة تحت المقارنة الصارمة";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
▶ جرّب الكود

مثال: جميع أنواع البيانات في لمحة

HTML
<!DOCTYPE html>
<html lang="ar">
<head>
  <meta charset="UTF-8">
  <title>أنواع البيانات - نظرة عامة كاملة</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 60px auto; }
    .type-card { display: inline-block; width: 120px; padding: 16px; margin: 6px; border-radius: 10px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s; }
    .type-card:hover { transform: scale(1.08); }
    .type-card h3 { margin: 0 0 4px; font-size: 14px; opacity: 0.9; }
    .type-card p { margin: 0; font-size: 12px; font-family: Consolas, monospace; }
    .string { background: #4CAF50; }
    .number { background: #2196F3; }
    .bigint { background: #e91e63; }
    .boolean { background: #FF9800; }
    .undef { background: #9E9E9E; }
    .nul { background: #795548; }
    .symbol { background: #00BCD4; }
    .object { background: #9C27B0; }
    #detail { margin-top: 20px; padding: 20px; background: #f5f5f5; border-radius: 8px; font-size: 16px; line-height: 1.8; display: none; }
  </style>
</head>
<body>
  <h2>أنواع البيانات الثمانية في JS</h2>
  <div class="type-card string" onclick="showDetail('string')"><h3>String</h3><p>"مرحبا"</p></div>
  <div class="type-card number" onclick="showDetail('number')"><h3>Number</h3><p>42</p></div>
  <div class="type-card bigint" onclick="showDetail('bigint')"><h3>BigInt</h3><p>900n</p></div>
  <div class="type-card boolean" onclick="showDetail('boolean')"><h3>Boolean</h3><p>true</p></div>
  <div class="type-card undef" onclick="showDetail('undefined')"><h3>Undefined</h3><p>undefined</p></div>
  <div class="type-card nul" onclick="showDetail('null')"><h3>Null</h3><p>null</p></div>
  <div class="type-card symbol" onclick="showDetail('symbol')"><h3>Symbol</h3><p>Symbol()</p></div>
  <div class="type-card object" onclick="showDetail('object')"><h3>Object</h3><p>{key:"val"}</p></div>
  <div id="detail"></div>
  <script>
    function showDetail(type) {
      var detailEl = document.getElementById("detail");
      detailEl.style.display = "block";
      var info = {
        "string": "String\nنص ملفوف بعلامات اقتباس: \"مرحبا\"، 'عالم'\ntypeof → \"string\"\nيمكن ربطه بـ +",
        "number": "Number\nأعداد صحيحة وعشريات: 42، 3.14، -7\nقيم خاصة: Infinity، -Infinity، NaN\ntypeof → \"number\"",
        "bigint": "BigInt\nيمثل أعدادًا صحيحة تتجاوز النطاق الآمن لـ Number\nالبناء: أضف n بعد الرقم، مثلاً 9007199254740991n\ntypeof → \"bigint\"",
        "boolean": "Boolean\nقيمتان فقط: true و false\nتُستخدم عادةً في الشروط\ntypeof → \"boolean\"",
        "undefined": "Undefined\nالقيمة الافتراضية للمتغيرات المعلنة غير المعينة\ntypeof → \"undefined\"\nيعني \"لا قيمة بعد\"",
        "null": "Null\nالمطور يعيّنه صراحة كـ \"فارغ\"\ntypeof → \"object\" (خطأ تاريخي!)\nnull === undefined هو false",
        "symbol": "Symbol\nأُضيف في ES6، يُنشئ معرّفات فريدة\nكل Symbol() مختلف\ntypeof → \"symbol\"\nيُستخدم عادةً كمفاتيح خصائص الكائن",
        "object": "Object\nنوع مرجعي، يخزن أزواج مفتاح-قيمة\nالمصفوفات []، الدوال، والتواريخ كلها كائنات\ntypeof → \"object\""
      };
      detailEl.textContent = info[type];
    }
  </script>
</body>
</html>
▶ جرّب الكود

📖 ملخص

  1. لدى JS 8 أنواع بيانات: 7 بدائل + 1 نوع مرجعي (Object)
  2. عامل typeof يتحقق من الأنواع، لكن typeof null يعيد "object" — خطأ تاريخي
  3. + يربط عندما يكون هناك نص — "5" + 3 يعطي "53"، وليس 8`
  4. null يعني "فارغ عمدًا"; undefined يعني "لا قيمة بعد" — ليسا متساويين صارمًا
  5. استخدم Number() أو parseInt() للتحويل الصريح قبل العمليات الحسابية لتجنب فخاخ الإكراه الضمني
  6. المصفوفات [] أيضًا تُرجع "object" من typeof — استخدم Array.isArray() للتمييز بين المصفوفات والكائنات

❓ أسئلة شائعة

س لماذا يُرجع typeof null "object"؟
ج هذا خطأ تاريخي من الإصدار الأول من JS. في ذلك الوقت، استخدمت JS بتات منخفضة لتحديد الأنواع، وnull كانت جميع بتاتها المنخفضة صفراً — مثل مُعرّف الكائن — لذلك تم تصنيفها بشكل خاطئ. حاولوا إصلاحها لاحقًا، لكن تغييرها سيكسر الكثير من الكود الموجود،所以他 أصبح الخطأ دائمًا. إنه مثل مبنى بأساس مائل — يعيش فيه太多 أشخاص لهدمه.
س كيف أتحقق مما إذا كانت القيمة مصفوفة أم كائنًا عاديًا؟
ج typeof يُرجع "object" لكلتا المصفوفات والكائنات،所以他 لا يمكنه التمييز بينهما. الطريقة الصحيحة هي Array.isArray() — على سبيل المثال، Array.isArray([1,2]) يُرجع true، بينما Array.isArray({}) يُرجع false.
س ما نوع NaN؟
ج NaN (ليس رقمًا) لديه typeof NaN يُرجع "number". الأكثر غرابة أن NaN === NaN يُرجع false — ليس حتى مساويًا لنفسه. استخدم isNaN() أو Number.isNaN() للتحقق من NaN.

📝 تمارين

  1. أساسي: أعلن 6 متغيرات لـ 6 أنواع بدائل (String، Number، Boolean، Undefined، Null، Object)، استخدم typeof على كل منها، واعرض النتائج على الصفحة.
  2. متوسط: أنشئ صفحة بها حقل إدخال. عندما يدخل المستخدم أي قيمة، يكتشف JS نوعها باستخدام typeof ويعرض النتيجة. جرّب إدخال أرقام، نصوص، true، null، إلخ، ولاحظ مخرجات typeof.
  3. تحدي: أنشئ صفحة "اختبار فخاخ الأنواع" بها 5 أسئلة اختيار من متعدد تختبر معرفة إكراه الأنواع، مثل ما قيمة "1" + 2، وما إذا كان null == undefined صحيحًا أم خاطئًا، إلخ. اعرض تغذية راجعة صحيحة/خاطئة مع التفسيرات عندما ينقر المستخدم على خيار.
100%