مقدمه

این درس به یکی از مهمترین و بنیادی‌ترین مباحث جاوااسکریپت یعنی تبدیل نوع (type conversion) اختصاص دارد. تبدیل نوع یک مفهوم کلی در برنامه‌نویسی است و هر زبانی قوانین خودش را در این مورد دارد. در اینجا ابتدا با مفهوم تبدیلات ضمنی و صریح و سپس با قوانین تبدیل نوع در جاوااسکریپت آشنا می‌شویم.

تبدیلات ضمنی و صریح

تبدیل نوع‌‌ها به یکدیگر به دو روش مختلف قابل انجام است: یکی تبدیل ضمنی (implicit conversion) که توسط مفسر و بدون نیاز به دخالت برنامه‌نویس انجام می‌شود و دیگری تبدیل صریح (explicit conversion) که توسط برنامه‌نویس درخواست می‌شود. اما موضوع مهم این است که اگرچه تبدیلات ضمنی به صورت خودکار انجام می‌شوند، اما ما باید از قوانین مربوط به آنها مطلع باشیم تا با نتایج غیر قابل انتظار مواجه نشویم.

اهمیت درک قوانین تبدیل نوع در جاوااسکریپت

مایلم به عنوان کسی که سال‌هاست با جاوااسکریپت سر و کله زده و به قول معروف، بالا و پایینش را دیده، رازی را برایتان افشا کنم: خیلی از افرادی که رابطه‌ی خوبی با جاوااسکریپت ندارند، قوانین تبدیل نوع در جاوااسکریپت را بلد نیستند یا خوب درک نکرده‌اند. به خصوص افرادی که سابقه‌ی کار با زبان‌هایی را دارند که در کار با مقادیر و داده‌ها سخت‌گیرند و تبدیلات ضمنی در آنها به‌ندرت رخ می‌دهد، سطح بالای تبدیلات ضمنی در جاوااسکریپت برایشان عجیب به نظر می‌رسد و با تصور ذهنی آنها سازگار نیست. اینجا افراد در مواجهه با جاوااسکریپت به دو گروه تقسیم می‌شوند؛ بعضی‌ها این تفاوت را برنمی‌تابند و حاضر نیستند بپذیرند که هر زبانی جهان‌بینی و فلسفه‌ی خودش را دارد اما بعضی دیگر این موضوع را درک کرده و می‌پذیرند و بعد از تسلط به قوانین تبدیل نوع در جاوااسکریپت، متوجه می‌شوند که این زبان چطور کارهایی را که انجامشان در سایر زبان‌ها سخت است، به سادگی انجام می‌دهد.

زبان‌هایی که سطح تبدیلات ضمنی در آنها پایین‌تر است، از ما انتظار دارند در هر جایی نوع داده‌ی مناسب را وارد کنیم. در چنین زبان‌هایی اگر در یک عبارت x * y مقادیر غیر عددی به‌جای x و y وارد کنیم یا در یک گزاره‌ی if(x) {…} مقدار غیر بولینی به‌جای x وارد کنیم، با خطا مواجه می‌شویم. اما در جاوااسکریپت، در چنین شرایطی به‌جای اعلام خطا، مقادیر وارد شده به نوع مورد نظر تبدیل می‌شوند. حالا ما به‌عنوان برنامه‌نویس جاوااسکریپت باید بدانیم که این تبدیلات بر اساس چه قوانینی انجام می‌شوند و این موضوعی است که در ادامه به آن می‌پردازیم.

تبدیل به رشته

تبدیل به string زمانی رخ می‌دهد که به فرم رشته‌ای یک مقدار نیاز باشد. برای مثال، وقتی از متد console.log() استفاده می‌کنیم، آرگومان این متد از هر نوعی که باشد، به طور ضمنی به رشته تبدیل می‌شود.

اما برای تبدیل صریح به رشته باید از یک تابع به نام String() استفاده کنیم. به طور کلی، متناظر با هر نوع، یک تابع همنام با آن نوع (ولی به صورت Capitalize) وجود دارد که مقادیر سایر نوع‌ها را به آن نوع تبدیل می‌کند. مثال زیر را ببینید.

> String(10);
"10"
> String(true)
"true"
> String(null)
"null"
          

همانطور که می‌بینید، تبدیل به string فرم بسیار ساده و قابل انتظاری دارد و به توضیح خاصی هم نیاز ندارد.

تبدیل به عدد

تبدیل به نوع number در توابع و عبارات ریاضی به طور ضمنی رخ می‌دهد. یعنی مثلاً در عبارتی مثل a * b اگر a و b از نوع number نباشند، به طور خودکار به number تبدیل می‌شوند. هر مقدار از هر نوعی که باشد، یک مقدار عددی معادل دارد. جدول زیر معادل عددی مقادیر سایر نوع‌ها را نشان می‌دهد.

مقدار معادل عددی
string کاراکترهای whitespace از ابتدا و انتهای رشته حذف می‌شوند. اگر رشته‌ی باقیمانده تهی بود، معادل صفر در نظر گرفته می‌شود و اگر عددی در رشته باقی مانده باشد، به آن عدد و در غیر این صورت به NaN تبدیل می‌شود.
boolean مقدار true به 1 و مقدار false به صفر تبدیل می‌شود.
null مقدار null به صفر تبدیل می‌شود.
undefined مقدار undefined به NaN تبدیل می‌شود.

پس، هر مقداری یک معادل عددی دارد و در هر جایی از برنامه که انتظار ورود عدد باشد اما یک مقدار غیر عددی وارد شود، آن مقدار به معادل عددی‌اش تبدیل می‌شود. حالا مثال زیر را ببینید.

> 5 * "10"
50 
> "6" / "2"
3
> "   12   " * 2
24
> "a123" * 2 
NaN
> 5 * false
0
> true / false
Infinity
> null * 2 
0
> 5 - undefined
NaN
          

وقتی در عبارتی از عملگرهای محاسباتی استفاده می‌شود، انتظار می‌رود که عملوندها عدد باشند و بنابراین، در مثال بالا عملوندها مطابق جدول بالا به مقدار عددی معادلشان تبدیل شده‌اند.

وجود NaN در هر عمل محاسباتی باعث تولید خود NaN می‌شود. فقط یک استثنا برای این قانون داریم و آن این است که NaN به توان صفر برابر با 1 است. در واقع، این که هر مقدار عددی به توان صفر برابر با 1 است، قانون محکم‌تری است که هیچ استثنایی ندارد.

در مورد تبدیل صریح به مقادیر عددی هم همانند آنچه در مورد نوع string هم دیدیم، یک تابع با نام Number() وجود دارد که آرگومان خود را به مقدار عددی معادلش تبدیل می‌کند. مثال زیر را ببینید.

> Number(true)
1
> Number("Hi")
NaN
> Number(null)
0
> Number(undefined)
NaN
          

برای تابع تبدیل Number() یک فرم کوتاه‌تر هم وجود دارد. می‌توانیم به‌جای اسم این تابع از عملگر + استفاده کنیم. برای مثال، Number(true) با +true معادل است.

تبدیل به بولین

اگر در جایی از برنامه که انتظار مقادیر بولین وجود دارد (مثل گزاره‌های شرطی یا عبارات منطقی) یک مقدار غیر بولین وارد شود، به طور ضمنی به بولین تبدیل می‌شود. قوانین تبدیل به بولین کاملاً سرراست و قابل انتظار است:

  • هر مقداری که شهوداً به معنای تهی باشد، به false تبدیل می‌شود. یعنی رشته‌های خالی، عدد صفر، مقدار NaN، مقدار null و undefined به false تبدیل می‌شوند. این مقادیر را از این رو که در تبدیل به بولین، به False تبدیل می‌شوند، مقادیر Falsy می‌گویند.
  • سایر مقادیر به مقدار true تبدیل می‌شوند. این مقادیر را هم Truthy می‌گویند
  • توجه داشته باشید که در اینجا بر خلاف تبدیل به مقادیر عددی، رشته‌ای که فقط شامل کاراکترهای whitespace باشد، خالی محسوب نمی‌شود و به true تبدیل می‌شود.

    تبدیل صریح به مقادیر بولین نیز با استفاده از تابع تبدیل Boolean() انجام می‌شود. مثال زیر را ببینید.

    > Boolean("")
    false
    > Boolean("  ")
    true
    > Boolean("Hi")
    true
    > Boolean(-1)
    true
    > Boolean(0)
    false
    > Boolean(NaN)
    false
    > Boolean(null)
    false
    > Boolean(undefined)
    false
                

    اینها قوانین تبدیل ضمنی و صریح برای نوع‌های primitive بودند که باز هم تأکید می‌کنم خیلی مهم است که آنها را به‌خوبی یاد بگیرید. در مورد قوانین تبدیل نوع object در آینده و بعد از آشنایی با این نوع صحبت خواهیم کرد. اما در درس بعدی، عملگرهای جاوااسکریپت را معرفی می‌کنیم و ضمن این کار، مرور مجددی هم بر قوانین تبدیل خواهیم داشت.