مقایسه

مقایسه در جاوااسکریپت

همه‌ی ما عملگرهای مقایسه‌ای را در ریاضی یاد گرفته‌ایم:

  • بزرگتر/کوچکتر : a > b , a < b .
  • بزرگتر مساوی / کوچکتر مساوی :‌ a >= b , a <= b .
  • برابری: a == b (حواستان باشد که برای مقایسه باید دو علامت مساوی پشت سر هم بنویسید. اگر فقط یک علامت مساوی بنویسید (a = b) برای ریختن مقدار درون متغیّر است، نه مقایسه).
  • نابرابری: در ریاضی علامت نابرابری ≠ است، اما به دلیل عدم وجود این علامت در صفحه‌کلید، در جاوااسکریپت به صورت != نوشته می‌شود. مثلاً a != b .

همیشه نتیجه‌ی مقایسه بولین است

مانند همه‌ی عملگرهای دیگر، عملگر مقایسه‌ای هم مقدار برمی گرداند؛ که این مقدار همیشه از نوع بولین است.

  • true – به معنی بله یا صحیح.
  • false – به معنی خیر یا غلط.

برای مثال:

alert( 2 > 1 );  // true (صحیح)
alert( 2 == 1 ); // false (غلط)
alert( 2 != 1 ); // true (صحیح)

می‌توان نتیجه‌ی مقایسه را مانند هر مقدار دیگری درون یک متغیر ریخت:

let result = 5 > 4; // نتیجه ی مقایسه را درون متغیر result می ریزد
alert( result ); // true

مقایسه‌ی رشته‌ها

بزرگتر یا کوچک بودن دو رشته طبق حروف الفبا تعیین می‌شود.

به عبارت دیگر، رشته حرف به حرف مقایسه می‌شود.

برای مثال:

alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Be' > 'Bee' ); // false

روش مقایسه‌ی رشته‌ها به این صورت است:

  1. اوّلین نویسه‌ی رشته‌ها (اوّلین حرف) با هم مقایسه می‌شود.
  2. اگر اوّلین نویسه‌ی رشته‌ی اوّل بزرگتر (یا کوچکتر) از رشته‌ی دیگر بود، پس آن رشته از دیگر بزرگتر (کوچکتر) است. این‌جا مقایسه تمام می‌شود.
  3. در غیر این صورت، یعنی اگر دو کاراکتر با هم برابر باشند، به همان روش بالا نویسه‌های دوم دو رشته با هم مقایسه می‌شود.
  4. این کار تا رسیدن به انتهای یکی از رشته‌ها تکرار می‌شود.
  5. اگر هر دو رشته با هم به انتها برسند و طول یکسانی داشته باشند، پس با هم برابر هستند. در غیر این صورت رشته‌ی طولانی تر بزرگتر است.

این همان روشی است که طبق آن، لیست اسامی را به ترتیب حروف الفبا مرتّب می‌کنند.

در مثال های بالا، مقایسه "Z" > "A" در قدم اول به نتیجه می‌رسد در حالی‌که رشته‌های "Glow" و "Glee" کاراکتر به کاراکتر با هم مقایسه می‌شوند:

  1. G با G برابر است.
  2. l با l برابر است.
  3. o بزرگتر از e است. مقایسه در اینجا به پایان می‌رسد. رشته‌ی اوّل بزرگتر است.

مقایسه‌ی رشته‌ها طبق فرهنگ لغت نیست، بلکه طبق کدِ نویسه‌هاست.

شیوه‌ای که در بالا توضیح داده شد تقریبا شبیه به ترتیبی است که در دفترچه تلفن و فرهنگ لغت داریم، امّا دقیقاً یکسان نیست.

مثلاً، بزرگی و کوچکی حروف در مقایسه‌ی رشته‌ها اهمیت دارد. حرف بزرگ "M" با حالت کوچکِ همان حرف "m" برابر نیست. کدامیک بزرگتر است؟! حرف کوچک "m"! چرا؟ چون در دنیای کامپیوتر به هر حرف و نویسه‌ای یک کدِ عددی اختصاص پیدا می‌کند، و مقایسه‌ی رشته‌ها با مقایسه‌ی آن کدها انجام می‌گیرد، و به صورت کلّی کُد حروف کوچک انگلیسی بزرگتر از حروف بزرگ است. در آموزش‌های بعدی بیشتر در این باره صحبت می‌کنیم.

مقایسه‌ی دیتاتایپ‌های مختلف

اگر مقادیری که با هم مقایسه می‌شود دیتاتایپ متفاوتی داشته باشند، جاوااسکریپت آن‌ها را به عدد تبدیل می‌کند.

برای مثال:

alert( '2' > 1 ); // true, رشته "۲" به عدد ۲ تبدیل می شود
alert( '01' == 1 ); // true, رشته ی "۰۱" به عدد ۱ تبدیل می شود

برای مقادیر بولین، true به ۰ و false به ۱ تبدیل می شود.

برای نمونه:

alert( true == 1 ); // true
alert( false == 0 ); // true

یک نتیجه‌ی بامزه

این امکان‌پذیر است که همزمان:

  • دو مقدار با هم برابر باشند.
  • یکی از آنها به عنوان بولین برابر با true شود و دیگری به عنوان بولین برابر با false شود!
let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!

مثال:

از زاویه دید جاوااسکریپتی، این نتیجه کاملاً عادی است. در مقایسه هر دو طرف به عدد تبدیل می‌شود (به همین خاطر "۰" می شود ۰) درحالی‌که تبدیل مستقیم این مقادیر به بولین از قوانین دیگری پیروی می‌کند.

بررسی برابری

عملگر مقایسه‌ایِ == یک مشکل بزرگ دارد. این مقایسه تفاوت میان ۰ و false را تشخیص نمی‌دهد:

alert( 0 == false ); // true

با رشته‌ی خالی نیز همین مشکل را داریم:

alert( '' == false ); // true

از آن‌جایی‌که عملگر == هنگام بررسی تساوی، مقادیر را به عدد تبدیل می کند. رشته‌ی خالی و false، هر دو به ۰ تبدیل می شوند.

برای آن که بتوانیم تفاوت میان ۰ و false را تشخیص دهیم، باید چه کار کنیم؟

عملگر === برابری دو مقدار را بدون آن که آنها را تبدیل کند، بررسی می‌کند.

به عبارت دیگر، اگر a و b دیتاتایپ متفاوتی داشته باشند، عبارت a === b مقدار false را بر می‌گرداند بدون آن که بخواهد دیتاتایپ آن‌ها را تغییر دهد.

بیایید این را امتحان کنیم:

alert( 0 === false ); // false, چون این دو دیتاتایپ های مختلفی دارند

جالب است بدانید که همین قضیه در مورد نابرابری نیز وجود دارد. یعنی عملگر != مانند == دو طرف را به عدد تبدیل می‌کند، ولی !== مانند === دیتاتایپ را عوض نمی‌کند، و در صورتی که دیتاتایپ متفاوت باشد false بر می‌گرداند.

alert( 0 !== false ); // true
//درست است که مقادیر عددی این دو با هم برابرند اما تایپ های متفاوتی دارند

اگر به این روش دو مقدار را با هم مقایسه کنید، کد طولانی‌تری می‌نویسید، اما جای اشتباه کمتری باقی می‌گذارد.

مقایسه‌ی null و undefined

در مورد مقایسه‌ی null یا undefined با سایر مقادیر نکته‌ای بسیار مهم وجود دارد، که مورد بررسی قرار می‌دهیم.

بررسی برابری با عملگر ===

این مقادیر با هم متفاوتند و رفتار جداگانه‌ای نشان می‌دهند. چون هر کدام آنها دیتاتایپ متفاوتی دارند.

alert( null === undefined ); // false

بررسی برابری با عملگر ==

در این حالت قانون خاص و مهمی وجود دارد: دو مقدار null و undefined با هم برابر هستند اما با هیچ مقدار دیگری برابر نیستند.

alert( null == undefined ); // true

عملیات ریاضی و سایر عملگرهای مقایسه‌ای < > >= <=

در این حالت null/undefined به عدد تبدیل می‌شود: null به ۰ تبدیل می‌شود و undefined به NaN تبدیل می‌شود.

حالا بیایید یک سری اتّفاقات جالب را که طبق این قوانین رخ می‌دهد بررسی کنیم و مهمتر از آن این‌که در دام آن‌ها نیفتیم.

نتیجه‌ی عجیب: null در مقابل ۰

بیایید null را با ۰ مقایسه کنیم:

alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true

از نظر ریاضی، این نتایج عجیب به نظر می‌رسد. نتیجه‌ی آخر می‌گوید که null بزرگتر یا مساوی ۰ است. بنابراین یکی از دو عبارت اوّل باید true باشد، اما هر دو false هستند! (جل الخالق ?)

دلیلش این است که بررسی برابری == و عملگرهای < > >= <= متفاوت عمل می‌کنند. عملگرهای مقایسه‌ای null را به عدد تبدیل می کنند و در نتیجه آن را به ۰ تعبیر می‌کنند. به همین دلیل است که نتیجه ی سوم true می شود و اولی false.

از طرف دیگر، عملگر == برای undefined و null به همان روشی عمل می‌کند که بالاتر شرح دادیم، تبدیل دیتاتایپ صورت نمی‌گیرد. در این حالت null و undefined با هم برابرند و با هیچ چیز دیگری برابر نیستند. به همین دلیل نتیجه‌ی دوم حاصل می‌شود.

undefined، موجودِ یکتا و بی‌همتا!

undefined نباید با مقادیر دیگر مقایسه شود:

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

چرا همیشه نتیجه false می شود؟

این نتایج را می‌بینیم چون:

  • مقایسه های اول و دوم false برمی گردانند چون undefined به NaN تبدیل می شود و NaN یک مقدار ریاضی ویژه است که در هر مقایسه مقدار false را ایجاد می کند.
  • بررسی برابری در مورد سوم false را برمی گرداند چون undefined تنها با null و undefined برابر است و نه هیچ مقدار دیگری.

فرار از این مشکلات

چرا این مثال ها را ذکر کردیم؟ آیا باید این ویژگی های جاوااسکریپت را همیشه به خاطر داشته باشیم؟! پاسخ منفی است. در واقع این نکات به تدریج برایمان عادی می شود و با آن‌ها خو می گیریم. اما راهی هم برای فرار از این مشکلات وجود دارد:

مقایسه های < > <= >= را برای مقادیری که ممکن است null/undefined باشند به کار نبرید، مگر آنکه دقیقا بدانید چه کاری دارید انجام می دهید. اگر یک متغیر ممکن است دارای این مقادیر باشد جداگانه آن‌ها را بررسی کنید.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *