25 - جاوااسکریپت: Comparison Operators

برای مثال اگر داشته باشیم console.log(1<2<3); به ما خروجی true میدهد. اگر داشته باشیم console.log(3<2<1); باز هم به ما خروجی true میدهد.چون عملگر > دارای associativity چپ به راست است. بنابراین در console.log(3<2<1); اول 3<2 اجرا میشود و مقدار false را برمیگرداند. بنابراین داریم false<1 که در آن js مقدار false را coerce میکنه و به عدد تبدیل میکنه.یک تابع built-in به اسم Number داریم. این تابع برای اینکه ببینیم چیزها به چی coerce میشوند خیلی مفید است. مثلا Number('3') خروجی 3 میدهد. یا Number(false) مقدار 0 را میدهد. بنابراین وقتی در کد بالا false<1 فراخوانی میشود، در واقع عبارت 0<1اجرا میشود و مقدار true را برمیگرداند.در مورد console.log(1<2<3); هم همین طور است. به ما خروجی true میدهد ولی به دلیل اینکه 1 کوچکتر از 2 و 2 کوچکتر از 3 است نیست.بنابراین coercion از نظر انسان ممکن است سبب نتایج عجیب شود ولی از نظر کامپیوتر کاملا منطقی است.اگر داشته باشیم Number(undefiend) به ما خروجی NaN را میدهد. NaN یک primitive type نیست ولی شبیه آنها میتوان در نظر گرفت. NaN یعنی این چیز را دارم که سعی شده به عدد تبدیل شود ولی راهی برای تبدیل آن به عدد نبوده.اگر داشته باشیم Number(null) به ما خروجی 0 میدهد.بنابراین همیشه واضح نیست که یک نوع مشخص به چه چیزی coerce میشود. موتور js تصمیم میگیرد. این مسئله اگر به درستی درک نشود میتواند باگهای عجیبی را سبب شود. پس coercion هم خیلی قدرتمند است و هم میتواند خیلی خطرناک باشد.عملگر == یا equality مساوی بودن دو متغیر را مشخص میدهد و معمولا در عبارات if می آید. مثلا اگر داشته باشیم 3 == 3 به ما خروجی true میدهد. اگر داشته باشیم '3' == 3 عملگر coerce را برای یک نوع انجام میدهد و خروجی true میدهد. اما همان طور که گفته شد coerce میتواند خطرناک باشد.عبارت false == 0 به خروجی true میدهد. عبارت null == 0 به ما خروجی false میدهد. بنابراین مواردی هست که طبق انتظار ما نیست، مثل null و undefined. عبارت null<1 به ما خروجی true میدهد. عبارت ""==0 خروجی true میدهد. عبارت ""==false هم خروجی true میدهد. js داره سعی میکنه مقادیر رو به نوع مشخص شده تبدیل کنه.بنابراین عملگر == و coercion میتواند نقطه ضعفی برای زبان js باشد. برای حل این مشکل از عملگر === یا strict equality استفاده میکنیم. این عملگر coercion را انجام نمیدهد. اگر دو مقدار از یک نوع نباشند مقدار false را برمیگرداند. برای مثال '3'===3 به ما خروجی false میدهد.بنابراین در وهله اول سعی کنید مقادیری را با هم مقایسه کنید که از یک نوع باشند. همچنین سعی کنید از === به جای == استفاده کنید. مگر این که آگاهانه بخواهید از coerce استفاده کنید.در سایت mozilla developer network در قسمت equality comparisons and sameness در مورد این مسئله صحبت شده و یک جدول با عنوان sameness comparisons داره که خروجی == و === رو برای نوع های مختلف نشون میده. علاوه بر == و === یک object.is داریم که جدیده و متغیرها را به is پاس میدهیم. در object.js مقدار صفر مثبت و صفر منفی یکی نیست ولی در == و === یکسان هست.27 - جاوااسکریپت: Existence, Booleansاز coercion کجا استفاده میشود؟یک تابع built-in دیگه به اسم Boolean هم داریم. توصیه میشود از این تابع استفاده نکنیم. اینجا برای نشان دادن مثالها از آن استفاده میکنیم.کد Boolean(undefined) به ما false برمیگرداند. کد Boolean(null) هم خروجی false میدهد. کد Boolean("") هم خروجی false میدهد. هر سه مقدار undefined و null و "" نشان دهنده عدم وجود هستند و به false تبدیل میشوند.هر مقداری را که داخل if () قرار میدهیم، سعی میکنه coerce به یک boolean کنه.var a;// goes to internet and looks for a valueif (a) { console.log('Something is there'); }در کد بالا از coercion برای بررسی اینکه آیا a هیچی است یا نه استفاده کردیم.کد Boolean(0) هم خروجی false میدهد. پس اگر در کد بالا در اینترنت مقدار a را 0 پیدا کند به مشکل برمیخوریم چون صفر همیشه به عنوان عدم وجود نیست. پس میتوانیم کد را به صورت زیر تغییر دهیم:if (a || a===0) { ... }بر حسب اولویت ها اول === اجرا میشود و بعد ||. در این کد داریم میگوییم که اگر a یه چیزی باشد ...28 - جاوااسکریپت: Default Valuesموارد دیگر استفاده از عملگرها و coercion:function greet(name) { console.log('Hello ' + name); }greet();اگر تابع را بدون هیچ پارامتری فراخوانی کنیم، برخلاف بسیاری دیگر از زبان های برنامه نویسی js خطا نمیدهد. خروجی میشود:Hello undefinedچون وقتی تابع فراخوانی میشود یک execution context ایجاد میشود و متغیر name که داخل تابع حتما ایجاد میشود undefined ست میشود. پس در js اگر تابع را بدون پارامتر فراخوانی کنیم آن را undefined در نظر میگیرد. چون متغیری است که در حافظه وجود دارد و مقدار جدیدی نگرفته است. داخل console.log که از + استفاده کردیم یک string و یک undefined میبیند. پس undefined را به string تبدیل میکند.اگر بخواهیم به جای این حالت برای name یک مقدار default داشته باشیم چه کنیم؟ در es6 سینتکسی معرفی میشود که مقدار پیش فرض را ست میکند. اما اگر به کدهای js در جاهای دیگه نگاه کنیم، از یک تریک برای ست کردن مقدار پیش فرض استفاده کرده اند:function greet(name) {name = name || '<Default value>';console.log('Hello ' + name);}عملگر || یک تابع است و فقط مقدار true یا false برنمیگرداند. اگر در console بنویسیم:undefined || 'hello'به ما مقدار "hello" را برمیگرداند. یعنی مقداری را برمیگرداند که میتواند به true م coerce شود. اگر در console بنویسیم:'hi' || 'hello'به ما مقدار "hi" یعنی اولین مقداری را که true میتواند coerce شود برمیگرداند.بنابراین میتوانیم از || به این صورت استفاده کنیم که اگر چیزی وجود نداشت، به ما مقدار پیش فرضی را برگرداند:undefined || 'hello'null || 'hello'"" || 'hello'همه اینها 'hello' را برمیگردانند.در کد تابع برای مقدار پیش فرض name اول name را نوشتیم و بعد <'Default value'> را. چون اگر name خالی نباشد عملگر || اولین مقدار غیرخالی را برمیگرداند. میتونستیم برای مقدار پیش فرض از if هم استفاده کنیم، ولی استفاده از || خیلی تمیزتر و کوتاه تر است.اگر تابع را به صورت greet(0) فراخوانی کنیم باز هم مقدار پیش فرض در name قرار میگیرد.