هر بار بحثی درمورد جاوااسکریپت میشه توی گروهها، با دریایی از memeها رو به رو میشیم. کافیه یکی بپرسه جاوااسکریپت زبان خوبیه؟ یا میخوام جاوااسکریپت رو شروع کنم…
توی این پست میخوایم یکی از معروفترینه این memeها رو بررسی کنیم و ببینیم که واقعا داستان پشتشون چیه و چرا جاوااسکریپت اینقدر احمق به نظر میاد. چون آخر کار ممکنه فراموش کنم این رو بنویسیم، همینجا میگم بهتون که اینا بامزه هستن و برای meme درست کردن خوبن، ولی توی کار واقعی به چنین مواردی بر نمیخورید احتمالا. اکثر اینها هم مربوط به جاوااسکریپت ES5 هست و تا حالا که نسخههای متعددی اومده و به استانداردهای ES9 رسیدیم، اکثر این بامزهها رو از دست دادیم و جایگزینهای بسیار کارایی براشون وجود داره. کافیست دیگه، بریم و شروع کنیم
typeof NaN
// "number"
1- مقدار NaN برای اعداد ناشناخته هست در نتیجه عدد هست (MDN)
9999999999999999
// 10000000000000000
2- جاوااسکریپت از float 64 بیتی استفاده میکنه، با Number.MAX_SAFE_INTEGER میتونید حداکثر عدد ممکن رو ببینید، کماکان میگم که توی پروژههای معمولی به حداکثر فلوت 64 بیتی رسیدن کار سادهای نیست ولی اگر رسیدید هم نگران نباشید، میتونید از MathJS استفاده کنید و هر عددی خواستید رو استفاده کنید (با استفاده از آرایهها عددها رو ذخیره میکنه)
0.5 + 0.1 == 0.6
// true
3- درمورد این حرفی برای زدن نیست، 0.6 با 0.6 برابر هست؟ بله هست
0.1 + 0.2 == 0.3
// false
4- این یکی خوبه واقعا، خوشم میاد از این
اینا داستان تبدیل عدد دودویی به دهدهی هست، مثلا عدد پی رو اگر در نظر بگیرید بی اندازه اعشار داره ولی فقط دو رقمش رو در نظر میگیریم، تبدیل اعدد اشاری دهدهی به دودویی هم داره همین داستان رو، بی اندازه اعشار داره که رُند میشه، در نتیجه عدد همیشه اونی که ما فکر میکنیم نیست
در واقع چیزی که داره مقایسه میشه اینا هستن…
0.1 + 0.2 = 0.30000000000000004
0.30000000000000004 == 0.3
// false
فقط هم مربوط به جاوااسکریپت نیست. راه حل هم براش زیاده ولی اینجا ساده و سر راست توضیح داده
Math.max()
// -Infinity
5- حداکثر مقدار یک آرایهی خالی، بیرون از آرایه قرار داره… در منفی بینهایت! شیوهی درست استفاده از این تابع ساده هست، Math.max(10, 5, 4, 9) و واقعا پیش نمیاد این ولی خوب منطقی هست که بزرگترین عدد آرایهی خالی بیرونش باشه
Math.min()
// Infinity
6- اینم مشابه بالایی هست، بیشترین از اون طرف لیست میافته بیرون، کمترین از این طرف اگر لیست کلا خالی باشه
;[] + []
// ""
7- علامت + هم برای concatenate یا چسبودن استفاده میشه هم برای جمع کردن (هرچند توی ES6 به بعد یه روش جایگزین خیلی خوب هست که میگم براتون)
خوب با توضیح بالا جاوااسکریپت تلاش میکنه این دو رو به هم بچسبونه و یک استرینگ تحویل بده. نتیجه میشه این
” ” + ” ” = ” “
;[] + {}
// "[object Object]"
8- نوع داده به سمت چپ تبدیل میشه، اینجا چون آرایه سمت چپ هست و قرار هست concatenate (چسبونده) بشه به بغلیش، آبجکت تبدیل به متن شده
{
}
;+[]
// 0
9- اینجا هم به نوع سمت چپ تبدیل میشه، در نتیجه
{} تبدیل به 0 شده
[] تبدیل به صفر شده
0 + 0 = 0
نکته: دلیل این تبدیلها، داینامیک تایپ بودن جاوااسکریپت هست، یعنی نیاز نیست شما نوع داده رو مشخص کنید مثل Cpp مثلا که اگر بخواید میتونید مشخص هم کنید با پیش پردازندهای مثل TypeScript یا FlowType، بستگی به نوع پروژتون داره و انتخابهای زیادی هم دارید همیشه
true + true + true
// 3
10- مقدار true همیشه ۱ هست و مقدار false همیشه ۰، یک استاندارد رایج بین زبونهای برنامه نویسی و حتی پایگاههای داده هست. در نتیجه که
1 + 1 + 1 === 3 ؟ بله هست
true - true
// 0
11- این همون داستان بالا هست، ۱ – ۱ میشه ۰
true == 1
// true
12- با همون تعریفهای بالا، ۱ == ۱ هست؟ بله
true === 1
// false
13- همونطور که میدونیم، === علاوه بر مقدار، نوع رو هم بررسی میکنه، این دو مقدارشون یکی هست ولی نوعشون خیر، درواقع
typeof true -> boolean
typeof 1 -> number
پس با اینکه مقدارشون یکی هست ولی چون نوعهاشون یکی نیست این مقایسه false میشه
;(!+[] + [] + ![]).length
// 9
14- روند اینم بامزه هست، ببینم با هم چه اتفاقی داره میافته
![] = false
(!+[]): true
([]+![]): "false" به عنوان متن
"truefalse" چسبیدن به عنوان دوتا متن
"truefalse".length = 9
در نتیجه در نهایت طول trueFalse سر هم باید حساب بشه که میشه 9 تا
9 + '1'
// 91
15- بالاتر هم درموردش گفتیم، اینجا + داره concatenate میکنه این دوتا رو به هم دیگه و ربطی به جمع نداره و حاصل استرینگ هست
91 - 1
// 90
16- اینجا عملگر – هر دو سمت رو عدد میکنه تا تفریق رو انجام بده، در نتیجه حاصل عدد هست
;[] == 0
// true
17- تبدیل [ ] به عدد که حاصل 0 هست و مقایسه با 0
برای نکات پایانی هم باید بدونیم که جاوااسکریپت چون وظیفهی اجرا شدن روی قدیمیترین مرورگرها تا پیشرفته ترین سرورها رو داره، چیزهایی که منسوخ شدن رو حذف نمیکنه، هستند ولی نباید توی نوشتن برنامهی تازه ازشون استفاده کنیم. حتما از ESLint و ابزارهای مشابه استفاده کنید تا درمورد چیزهای منسوخ شده بهتون هشدار بدن
برای چسبوندن متنها به هم و گذاشتن متغیر از این روش استفاده کنید
// !!! منسوخ شده !!!
var name = 'Saleh'
var age = 20
var city = 'Shiraz'
console.log(
'Name is ' +
name +
'\n' +
'Age is: ' +
age +
'\n' +
'City is: ' +
city +
'\n'
)
// ** استاندارد تازه **
const name = 'Saleh',
age = 20,
city = 'Shiraz'
console.log(`
Name is : ${name}
Age is: ${age}
City is: ${city}
`)
برای مقایسه هم همیشه از === استفاده کنید نه ==
و همینطور اگر کار جدیای با اعداد دارید، از کتابخونههای حرفهای مثل MathJS و… استفاده کنید تا احتمال اینکه در آینده برنامتون یه وقتی به مشکل بخوره رو کمتر کنید
و نکتهی نهایی اینکه زبونها برای استفاده هستند، از هرکدوم هرجایی که بهتر جواب میده استفاده کنید و لذت ببرید 📿🕶
منبع اصلی (dev.to)