المسارات
/
JavaScript
JavaScript
/
المنهج
/
تحويل الأنواع
تح

تحويل الأنواع في JavaScript

تمرينان

نبذة عن تحويل الأنواع

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

تحويل النوع

لا تملك JavaScript بنية لتحويل قيمة إلى نوع (مختلف) كما تفعل لغات أخرى كثيرة، لكن يمكن الاستعانة ببعض الأدوات المدمجة بدلًا من ذلك. وأبرزها أن الكائنات العامة Boolean وNumber وString يمكن استخدامها كدوال لتحويل قيمة إلى النوع المقابل.

التحويل إلى قيمة منطقية (القيم الصحيحة والقيم الخاطئة)

باستخدام Boolean(value) يمكنك تحويل أي قيمة إلى قيمة منطقية. فكيف يحدث ذلك؟

هناك مجموعة ثابتة من القيم، تُسمّى القيم الخاطئة، تتحول إلى false. وأهمها false و0 والسلسلة النصية الفارغة وnull وundefined وNaN، فهي كلها قيم خاطئة. ويعرض مقال MDN عن "Falsy" القائمة الكاملة.

أما جميع القيم الأخرى، فتُرجع Boolean القيمة true. وتُسمّى هذه القيم صحيحة.

Boolean(-1);
// => true

Boolean(0);
// => false

Boolean(' ');
// => true

Boolean('');
// => false

لاحظ أنه بفضل القواعد الموصوفة، فإن '0' و'false' و[] و{} تُعد صحيحة في JavaScript.

التحويل إلى عدد

يمكن استخدام Number(value) لتحويل قيمة إلى عدد. تُتجاهل المسافات البيضاء في بداية السلسلة النصية ونهايتها، وتُحوَّل السلسلة النصية الفارغة إلى 0. وإذا حاولت تحويل قيمة غير أولية أو سلسلة نصية لا تمثّل عددًا، فلن يُطرح أي خطأ. بل ستكون النتيجة NaN (ليس عددًا).

Number('  -12.34  ');
// => -12.34

Number('1,2');
// => NaN

Number('1 2');
// => NaN

Number('');
// => 0

Number('10e3');
// => 10000

Number({ key: '123' });
// => NaN

وفي الأسفل ترى ما تُرجعه Number لبقية القيم الأولية.

Number(true);
// => 1

Number(false);
// => 0

Number(null);
// => 0

Number(undefined);
// => NaN

لاحظ أنه بخلاف المثال الأخير، فإن استدعاء Number() دون أي وسيط مُعرَّف بأنه يُرجع 0.

وتوفّر JavaScript أيضًا الدالتين parseInt وparseFloat. وهما تطبّقان قواعد أكثر تسامحًا فيما يخص السلاسل النصية التي يمكن تحويلها إلى عدد. ولهذا يُفضَّل استخدام Number كدالة تحويل لتجنّب نتائج غير متوقعة.

parseInt('123a45');
// => 123

Number('123a45');
// => NaN

التحويل إلى سلسلة نصية

باستخدام String(value) يمكنك تحويل قيمة إلى سلسلة نصية. وتكون النتيجة كما تتوقعها بالنسبة إلى القيم الأولية.

String(12.34);
// => '12.34'

String(false);
// => 'false'

String(null);
// => 'null'

String(undefined);
// => 'undefined'

أما المصفوفات، فستُطبّق دالة String تحويل السلسلة النصية على كل عنصر ثم تدمج النتائج بفاصلة. ويمكنك أيضًا استخدام طريقة join بنفسك، مثلًا لتخصيص الفاصل. غير أنه في هذه الحالات تُحوَّل null وundefined إلى سلسلة نصية فارغة.

String([42, null, true, 'abc']);
// => '42,,true,abc'

أما الكائنات، فتُرجع String افتراضيًا نصًا غير مفيد.

String({ key: 'value' });
// => '[object Object]'

ويمكنك تخصيص سلوك التحويل، مثلًا بتوفير طريقة toString. ويشرح قسم "تحويل الكائن إلى قيمة أولية" على javascript.info التفاصيل.

وثمة طريقة شائعة أخرى للحصول على تمثيل نصي أفضل للكائنات والمصفوفات، وهي استخدام ترميز JSON. فيمكنك التحويل إلى سلسلة نصية عبر JSON.stringify، والعودة إلى كائن أو مصفوفة عبر JSON.parse.

const obj = {
  name: 'Gilda Guerra',
  address: {
    city: 'Goiânia',
  },
};

JSON.stringify(obj);
// => '{"name":"Gilda Guerra","address":{"city":"Goiânia"}}'

الإكراه النوعي

في سياقات معينة، تُحوّل JavaScript تلقائيًا قيمة إلى نوع بيانات آخر قبل أن تُقيّم عبارة ما. ويُسمّى هذا التحويل الضمني الإكراه النوعي.

السياق المنطقي

عندما تُستخدم قيمة في سياق منطقي، تُطبّق JavaScript القواعد نفسها التي تطبّقها دالة Boolean لتحويل القيمة ضمنيًا.

  • عندما لا يكون شرط الجملة الشرطية قيمة منطقية، يُطبَّق الإكراه لتحديد ما إذا كان الشرط قد تحقق أم لا. وينطبق الأمر نفسه على الطرف الأول من العامل الثلاثي ?.

    const num = 0;
    if (num) {
      // this block is NOT executed because 0 is falsy
    }
    
    const name = 'Jin';
    name ? 'name was provided' : 'no name provided';
    // => 'name was provided'
    
  • كما يُحوَّل طرف عامل النفي المنطقي ! إلى قيمة منطقية قبل تطبيق عملية النفي.

    const name = '';
    !name;
    // => true
    

    ومن نتائج السلوك الموصوف أن !!value لها الأثر نفسه الذي ينتج عن Boolean(value). ومع ذلك، يُستحسن استخدام Boolean لوضوح القراءة.

  • وتطبّق JavaScript أيضًا الإكراه على طرفَي العاملين المنطقيين AND (&&) وOR (||). لكن تذكّر أن ناتج التعبير ليس بالضرورة قيمة منطقية. بل يُرجع أحد الطرفين الأصليين (انظر توثيق MDN للعوامل المنطقية).

    null || 'hello';
    // => 'hello'
    

سياق السلسلة النصية

إذا استُخدم عامل الجمع + مع قيم أولية وكان أحد الطرفين سلسلة نصية، فسيُحوَّل الطرف الآخر إلى سلسلة نصية أيضًا. ومنطق التحويل هو نفسه المستخدم في دالة String. بعد ذلك تُدمج السلسلتان النصيتان.

let name;
'hello ' + name;
// => 'hello undefined'

ويحدث التحويل الضمني نفسه للقيم غير النصية التي تُضمَّن في القوالب النصية.

const degrees = 23;
`It is ${degrees} °C`;
// => 'Is is 23 °C.';

السياق العددي

تحوّل عوامل كثيرة أطرافها إلى أعداد (عند الحاجة) وفق منطق دالة Number الموضّح أعلاه.

  • عوامل الحساب: + (إذا لم تكن هناك سلسلة نصية)، و-، و*، و/، و%، و**
  • عاملا الجمع الأحادي والنفي الأحادي: +، -
  • عوامل المقارنة العلائقية (للأطراف غير النصية): >، >=، <، <=
  • عوامل العمليات البِتّية: |، &، ^، ~

راجع قائمة العوامل في MDN لمزيد من التفاصيل عن أي منها.

عندما يكون أحد الأطراف سلسلة نصية محتملة، فالأفضل دائمًا التحويل صراحةً بدالة Number لتجنّب الأخطاء.

'1' + '2';
// => '12'
// addition operator in string context as explained above

Number('1') + Number('2');
// => 3

أحيانًا سترى عامل الجمع الأحادي يُستخدم لإكراه سلسلة نصية لتصبح عددًا. ولا يُنصَح بهذا، لأنه أصعب في القراءة بكثير من استدعاء Number الصريح.

const value = '42';
+value;
// => 42

Number(value);
// => 42

كذلك غالبًا ما يتضمن استخدام عاملي المساواة وعدم المساواة غير الصارمتين ==/!= تحويلًا ضمنيًا إلى عدد. غير أن المنطق الدقيق لهذين العاملين معقّد نوعًا ما (انظر توثيق MDN للمساواة غير الصارمة). ونتابجهما صعبة التوقع، وأحيانًا ليست ما تتوقعه. فاستخدم بدلًا منهما عاملي المساواة وعدم المساواة الصارمتين ===/!== لتجنّب هذه التحويلات الضمنية.

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم تحويل الأنواع