IsNumeric في JavaScript: 5 أخطاء قاتلة عند التحقق من صحة الأرقام

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التحقق من صحة الأرقام العشرية في JavaScript: لماذا يكسر IsNumeric() الكود وكيفية إصلاح ذلك

\n\n

كل مطور كتب بلغة JavaScript لمدة أسبوع على الأقل، عاجلاً أم آجلاً، واجه مهمة: "التحقق مما إذا كانت السلسلة النصية رقماً". قد يبدو الأمر بسيطاً؟ الدالة المضمنة isNaN() أو parseFloat() وستكون المهمة منتهية. لكن الأمر ليس بهذه السهولة. سؤال "Validate decimal numbers in JavaScript — IsNumeric()" على Stack Overflow حصد مئات الآلاف من المشاهدات وعشرات الإجابات المتناقضة. لماذا؟ لأن JavaScript هي لغة حيث typeof NaN === 'number'، والسلسلة الفارغة تُعتبر صفراً.

\n\n

في هذه المقالة، لن نقدم فقط دالة isNumeric() جاهزة. سنقوم بتحليل 5 أخطاء شائعة وخطيرة يرتكبها حتى المبرمجون ذوو الخبرة، وسنوضح كيفية تجنبها. ستتعرف على لماذا isNaN هو فخ، وكيف يعمل تحويل الأنواع، وأي طريقة للتحقق من صحة الأرقام في JS يجب استخدامها فعلياً في بيئة الإنتاج.

\n\n

لماذا isNaN() شريرة (ومتى تعمل)

\n\n

لنبدأ بالأمر الواضح. العديد من المبتدئين يكتبون هكذا:

\n\n
function isNumeric(n) {\n  return !isNaN(n);\n}\n
\n\n

للوهلة الأولى يبدو منطقياً: إذا لم يكن NaN، فهذا يعني أنه رقم. لكن دعنا نختبر:

\n\n
console.log(isNumeric('123'));    // true — صحيح\nconsole.log(isNumeric('12.3'));   // true — صحيح\nconsole.log(isNumeric(''));       // true — أوبس! السلسلة الفارغة رقم؟\nconsole.log(isNumeric(' '));      // true — المسافة أيضاً رقم؟\nconsole.log(isNumeric(null));     // true — null هو رقم؟\nconsole.log(isNumeric(true));     // true — true هو 1\n
\n\n

الخطأ رقم 1: isNaN() أولاً يحول الوسيطة إلى رقم، ثم يتحقق. السلسلة الفارغة '' تتحول إلى 0، null يتحول إلى 0، true يتحول إلى 1. ونتيجة لذلك، تعتبر الدالة ما ليس رقماً على أنه رقم.

\n\n

هناك خيار صارم — Number.isNaN() (ES6)، لكنه يتحقق فقط مما إذا كانت القيمة هي NaN بالضبط، دون تحويل. وهو أيضاً غير مناسب للتحقق من صحة الأرقام.

\n\n

parseFloat: بطل أم شرير؟

\n\n

النهج الشائع الثاني هو استخدام parseFloat():

\n\n
function isNumeric(n) {\n  return !isNaN(parseFloat(n)) && isFinite(n);\n}\n
\n\n

هذا الخيار أفضل، لكن لديه مشكلة أخرى:

\n\n
console.log(isNumeric('123abc')); // true — parseFloat سيأخذ '123' ويتجاهل 'abc'\nconsole.log(isNumeric('12.3.4')); // true — parseFloat لن يلاحظ النقطة الثانية\nconsole.log(isNumeric('Infinity')); // true — اللانهاية هل هي رقم؟\n
\n\n

الخطأ رقم 2: parseFloat() يحلل السلسلة حتى أول حرف غير صالح. السلسلة '123abc' بالنسبة له هي 123. لكن المستخدم ربما ضغط على مفتاح إضافي عن طريق الخطأ، ويجب علينا اكتشاف ذلك.

\n\n

الخطأ رقم 3: isFinite() يستبعد Infinity و -Infinity، لكنه يسمح بمرور NaN و undefined. المشكلة هي أن isFinite(null) يُرجع true، لأن null يتحول إلى 0.

\n\n

الخطأ رقم 4: التعبيرات المنتظمة — حل سحري أم جحيم جديد؟

\n\n

عندما يدرك المطورون أن الدوال المضمنة غير موثوقة، غالباً ما يندفعون إلى الطرف الآخر — التعبيرات المنتظمة. وهنا تبدأ الفوضى الحقيقية.

\n\n

إليك تعبير منتظم نموذجي ولكنه خطير:

\n\n
function isNumeric(n) {\n  return /^\\d+$/.test(n);\n}\n
\n\n

المشاكل:

\n
    \n
  • لا يسمح بالنقاط العشرية ('12.3' — false)
  • \n
  • لا يسمح بالأرقام السالبة ('-5' — false)
  • \n
  • لا يسمح بالترميز العلمي ('1e5' — false)
  • \n
\n\n

إليك "ال

المدونات

توصيات الكتب