در 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 است (Not-A-Number).
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 دربارهی برابری سهلگیرانه را ببینید).
نتیجههایشان بهسختی قابل پیشبینی است و گاهی آن چیزی نیست که انتظار دارید.
برای پرهیز از این تبدیلهای ضمنی، بهجایش از عملگرهای برابری و نابرابری سختگیرانهی ===/!== استفاده کنید.