عملگرهای مقایسه ای زیادی را از ریاضی می شناسیم.
در جاوااسکریپت آن ها را مانند شکل زیر می نویسم:
- بزرگ تر / کوچک تر:
a > b،a < b. - بزرگ تر / کوچک تر یا مساوی:
a >= b،a <= b. - برابر یا مساوی:
a == b، توجه کنید که علامت مساوی دوتایی (double equlity)==به معنای تست برابری است، در حالی که یک مساویa = bمقدار سمت راست را در متغیر سمت چپ می ریزد.(asign). - نابرابری: در ریاضی علامت نابرابری
≠است، اما در جاوااسکریپت به صورتa != bنوشته میشود.
در این مقاله ما بیشتر درباره تفاوت انواع مقایسه ها، چطور جاوااسکریپت آنها را انجام می دهد، به همراه رفتارهای عجیب و مهم این زبان.
در انتها شما می توانید به راحتی از از مشکلات مربوط به علامت ها دوری کنید.
تمام عملگرهای مقایسه ای یک مقدار از نوع boolean برمی گردانند:
true-- به معنای "بله" و "درست" است.false-- به معنای "نه" و "غلط" است.
برای مثال:
alert( 2 > 1 ); // true (درست)
alert( 2 == 1 ); // false (غلط)
alert( 2 != 1 ); // true (درست)نتیجه یک مقایسه می تواند داخل یک متغیر ذخیره شود، دقیقا مانند هر مقدار دیگری:
let result = 5 > 4; // assign the result of the comparison
alert( result ); // trueبرای این که متوجه شموی که آیا یک رشته بزرگ تر از رشته ی دیگر هست یا نه، جاوااسکریپت از یک مفهوم به نام "dictionary" یا "lexicographical order" استفاده می کند.
به عبارت دیگر، رشته ها حرف به حرف با یکدیگر مقایسه می شوند.
برای مثال:
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // trueالگوریتمی که برای مقایسه دو رشته استفاده می شود بسیار ساده است:
- اولین کاراکتر هر دو رشته را با هم مقایسه کن.
- اگر اولین کاراکتر رشته اول بزرگ تر (یا کوچک تر) از اولین حرف رشته دیگر بود، آنگاه رشته اول بزرگ تر ( یا کوچک تر) از رشته دوم است و الگوریتم به پایان می رسد.
- در غیر این صورت، اگر هر دو کاراکتر مانند هم بودند، حرف دوم رشته ها را به روش مرحله قبل با هم مقایسه می کند.
- این عمل را تا پایان یکی از رشته ها ادامه می دهد.
- اگر هر دو رشته با هم به پایان برسند، در آن صورت آن ها مساوی هستند. در غیر این صورت، رشته بزرگتر بزرگ تر است.
در مثال بالا، مقایسه 'Z' > 'A' در اولین مرحله به نتیجه می رسد.
درحالی که رشته های 'Glow' و 'Glee' حرف به حرف با هم مقایسه می شوند:
Gدقیقا مانندGاست.lدقیقا مانندlاست.oازeبزرگ تر است. الگوریتم در این جا به پایان می رسد و نتیجه می گیرد که رشته اول بزرگ تر است.
ترتیب و ارزشی که در الگوریتم مقایسه بالا به هر حرف داده می شود، تقریبا مانند دیکشنری ها یا کتاب های تلفن است، اما نه دقیقا مشابه آن ها.
برای مثال، بزرگ یا کوچکیه حروف اهمیت دارند. حرف `"A"` بزرگ با حرف `"a"` کوچک برابر نیست. حتما می پرسید کدام یک بزرگ تر است؟ جواب حرف `"a"` کوچک است. چرا؟ به دلیل اینکه حرف "a" کوچک دارای شماره بزرگتری در جدول encoding ٔداخلی خود جاوااسکریپت دارد. (Unicode). ما بعدا در فصل رشته ها به این موضوع مفصل می پردازیم. <info:string>.
وقتی که مقادیر با نوع های متفاوت را در جاوااسکریپت با یکدیگر مقایسه می کنید، جاوااسکریپت مقادیر را به نوع داده Number تبدیل می کند.
برای مثال:
alert( '2' > 1 ); // true، رشته '2' به عدد 2 تبدیل می شود.
alert( '01' == 1 ); // true، رشته '01' به عدد 1 تبدیل می شود.برای مقادیر از نوع true boolean به 1 و false به 0 تبدیل می شود.
برای مثال:
alert( true == 1 ); // true
alert( false == 0 ); // trueاین امکان وجود دارد که همزمان:
- دو مقدار با هم مساوی باشند.
- یکی از آن ها در نوع `false` boolean است و دیگری `true`.
برای مثال:
```js run
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
```
از نظر جاوااسکریپت، این تنیجه کاملا عادی است. علامت برابری (equality) = مقادیر را به number تبدیل کرده و سپس آن ها را با یکدیگر مقایسه می کند.(به همین دلیل `"0"` به `0` تبدیل می شود.) اما تبدیل آن ها به صورت جداگانه به `Boolean` از قانون های دیگری استفاده می کند.
یک علامت مقایسه برابری معمولی == یک مشکل دارد. این عملگر بین 0 و false تفاوتی قائل نمی شود:
alert( 0 == false ); // trueدقیقا همین اتفاق برای یک رشته خالی هم می افتد:
alert( '' == false ); // trueدلیل این اتفاق این است که مقادیر با نوع های متفاوت به نوع number توسط عملگر == تبدیل می شوند و یک رشته خالی دقیقا مانند مقدار false به صفر تبدیل می شود.
سوال اینجاست که ما چطور می توانیم بین false و 0 تفاوت ایجاد کنیم؟
عملگر مقایسه برابری سخت گیرانه (strict equality operator) === برابری را بدون تبدیل به نوع number انجام می دهد.
به عبارت دیگر، اگر نوع متغیر های a و b با یکدیگر متفاوت باشد، در این صورت عملیات a === b بالافاصله مقدار false را برمی گرداند و عمل تغییر نوع داده را انجام نمی دهد.
بیاید امتحان کنیم:
alert( 0 === false ); // false، به خاطر اینکه نوع آن ها با یکدیگر متفاوت است.یک علامت "مقایسه نابرابری سختگیرانه" (strict non-equality operator) !== هم وجود دارد در کنار عملگر مقایسه نابرابری !=.
نوع سختگیرانه این عملگرها در زمان نوشتن کمی طولانی تر می شوند، اما به وضوح مشخص می کند که چه اتفاقی در پشت پرده در حال افتادن است و احتمال خطا را کاهش می دهد.
در زمان مقایسه مقادیر متفاوت با null و undefined یک رفتار غیر قابل پیش بینی اتفاق می افتد.
در زمان استفاده از عملگر برابری سختگیرانه ===
: این دو مقدار با یکدیگر نا برابرند به دلیل اینکه از دو نوع متفاوت هستند.
```js run
alert( null === undefined ); // false
```
در زمان استفاده از عملگر برابری غیر سختگیرانه ==
: یک قانون خاص وجود دارد. تنها این دو با هم برابرند و نه با هیچ مقدار دیگری
```js run
alert( null == undefined ); // true
```
برای ریاضی و دیگر مقایسه ها < > <= >=
: null/undefined به عدد تبدیل می شوند: null تبدیل به 0 می شود در حالی که undefined به NaN.
حال بگذارید چند اتفاق با مزه و جالب که با اعمال این قانون ها می افتند را ببینیم. و مهم تر از همه ببینیم که چگونه داخل این تله ها نیفتیم.
مقایسه مقدار null با صفر:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!*از نظر ریاضی، این ۳ عبارت با هم هم خوانی ندارند. عبارت آخر مشخص می کند که "null بزرگ تر یا مساوی 0" است، پس منتطقا یکی از دو عبارت اول باید true باشند درحالی که هر دو false هستند.
دلیل این اتفاق این است که عملگر == و > < >= <= متفاوت با یکدیگر عمل می کنند. علامت های مقایسه ای مقدار null را به یک عدد تبدیل می کنند، و با آن مانند عدد 0 رفتار می کنند. به همین دلیل عبارت (۳) true است و عبارت (۱) false.
از طرفی ، عملگر == مقادیر undefined و null را با هم برابر و نابرابر با هر مقدار دیگری در نظر می گیرد، به همین دلیل عبارت شماره (۲) false است.
مقدار undefined نباید با دیگر مقادیر مقایسه شود:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)به نظر شما چرا undefiend انقدر از صفر بدش می آید که در تمام حالات false برمی گرداند!
دلیل این نتایج:
- در عبارت شماره
(1)و(2)مقدارundefinedبه مقدارNaNتبدیل می شود که یک نوع خاص از number ها است که در تمام مقایسه هاfalseبرمی گرداند. - در عبارت
(3)عملگر==،falseبرمی گرداند زیراundefinedتنها برابرnullبوده و نابرابر با هر مقدار دیگری.
چرا ما این مثال ها را بررسی کردیم؟ آیا ما این رفتار های عجیب را باید همیشه به خاطر داشته باشیم؟ در حقیقت نیازی به این موضوع نیست. زیرا در گذر زمان و به صورت تدریجی این رفتار های برای شما آشنا می شوند، اما یک راه حل کاربردی و مطمئن برای دوری از این مشکلات وجود دارد:
- با احتیاط و ملاحظه از
undefined/nullدر مقایسه های خود استفاده کنید به جزء زمانی که از عملگر===استفاده می کنید. - از علامت های مقایسه ای
>= > < <=برای مقایسه مقادیری که ممکن ازundefined/nullشوند استفاده نکنید مگر اینکه واقعا متوجه عواقب کارهای خود هستید. اگر متغیری می تواند این مقادیر را داشته باشد، آن ها را به صورت جداگانه بررسی کنید.
<<<<<<< HEAD
- عملگرهای مقایسه یک مقدار boolean را برمی گردانند.
- رشته ها به صورت حرف به حرف با توجه به ترتیب حروف در "دیکشنری" با هم مقایسه می شوند.
- وقتی که مقادیری با نوع های متفاوت با یکدیگر مقایسه می شوند، به نوع number تبدیل می شوند (بدون در نظر گرفتن حالت استفاده از عملگر === ).
- مقادیری
nullوundefinedبا یکدیگر برابر==و با هر مقدار دیگری نابرابرند. - زمانی که از علامت ها
>یا<برای مقایسه متغیر هایی که می توانند مقدارnull/undefinedداشته باشند استفاده می کنید، مراقب باشید. بررسی برای مقاریدnull/undefinedبه صورت جداگانه کار بسیار پسندیده ای است. ======= - Comparison operators return a boolean value.
- Strings are compared letter-by-letter in the "dictionary" order.
- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check).
- The values
nullandundefinedare equal==to themselves and each other, but do not equal any other value. - Be careful when using comparisons like
>or<with variables that can occasionally benull/undefined. Checking fornull/undefinedseparately is a good idea.
52c1e61915bc8970a950a3f59bd845827e49b4bf