عملگرهای مقایسه ای زیادی را از ریاضی می شناسیم.
در جاوااسکریپت آن ها را مانند شکل زیر می نویسم:
- بزرگ تر / کوچک تر:
a > b
،a < b
. - بزرگ تر / کوچک تر یا مساوی:
a >= b
،a <= b
. - برابر یا مساوی:
a == b
، توجه کنید که علامت مساوی دوتایی (double equlity)==
به معنای تست برابری است، در حالی که یک مساویa = b
مقدار سمت راست را در متغیر سمت چپ می ریزد.(asign). - نابرابری: در ریاضی علامت نابرابری
≠
است، اما در جاوااسکریپت به صورتa != b
نوشته میشود.
در این مقاله ما بیشتر درباره تفاوت انواع مقایسه ها، چطور جاوااسکریپت آنها را انجام می دهد، به همراه رفتارهای عجیب و مهم این زبان.
در انتها شما می توانید به راحتی از از مشکلات مربوط به علامت ها دوری کنید.
نتیجه یک boolean است
تمام عملگرهای مقایسه ای یک مقدار از نوع 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
مقایسه رشته ها (string)
برای این که متوجه شموی که آیا یک رشته بزرگ تر از رشته ی دیگر هست یا نه، جاوااسکریپت از یک مفهوم به نام “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). ما بعدا در فصل رشته ها به این موضوع مفصل می پردازیم. رشتهها.
مقایسه انواع متفاوت داده با یکدیگر
وقتی که مقادیر با نوع های متفاوت را در جاوااسکریپت با یکدیگر مقایسه می کنید، جاوااسکریپت مقادیر را به نوع داده 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
.
برای مثال:
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
در زمان مقایسه مقادیر متفاوت با null
و undefined
یک رفتار غیر قابل پیش بینی اتفاق می افتد.
- در زمان استفاده از عملگر برابری سختگیرانه
===
-
این دو مقدار با یکدیگر نا برابرند به دلیل اینکه از دو نوع متفاوت هستند.
alert( null === undefined ); // false
- در زمان استفاده از عملگر برابری غیر سختگیرانه
==
-
یک قانون خاص وجود دارد. تنها این دو با هم برابرند و نه با هیچ مقدار دیگری
alert( null == undefined ); // true
- برای ریاضی و دیگر مقایسه ها
< > <= >=
-
null/undefined
به عدد تبدیل می شوند:null
تبدیل به0
می شود در حالی کهundefined
بهNaN
.
حال بگذارید چند اتفاق با مزه و جالب که با اعمال این قانون ها می افتند را ببینیم. و مهم تر از همه ببینیم که چگونه داخل این تله ها نیفتیم.
نتایج عجیب: 0 در مقابل null
مقایسه مقدار 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 است.
undefiend غیرقابل مقایسه
مقدار 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
شوند استفاده نکنید مگر اینکه واقعا متوجه عواقب کارهای خود هستید. اگر متغیری می تواند این مقادیر را داشته باشد، آن ها را به صورت جداگانه بررسی کنید.
خلاصه
- عملگرهای مقایسه یک مقدار boolean را برمی گردانند.
- رشته ها به صورت حرف به حرف با توجه به ترتیب حروف در “دیکشنری” با هم مقایسه می شوند.
- وقتی که مقادیری با نوع های متفاوت با یکدیگر مقایسه می شوند، به نوع number تبدیل می شوند (بدون در نظر گرفتن حالت استفاده از عملگر === ).
- مقادیری
null
وundefined
با یکدیگر برابر==
و با هر مقدار دیگری نابرابرند. - زمانی که از علامت ها
>
یا<
برای مقایسه متغیر هایی که می توانند مقدارnull/undefined
داشته باشند استفاده می کنید، مراقب باشید. بررسی برای مقاریدnull/undefined
به صورت جداگانه کار بسیار پسندیده ای است.
نظرات
<code>
استفاده کنید، برای چندین خط – کد را درون تگ<pre>
قرار دهید، برای بیش از ده خط کد – از یک جعبهٔ شنی استفاده کنید. (plnkr، jsbin، codepen…)