بازگشت به دوره

عملگرهای منطقی (Logical Operators)

پیش از این با عملگرهای محاسباتی (و عملگر typeof) آشنا شدیم. اما در جاوا اسکریپت انواع دیگری از عملگرها نیز وجود دارد که قبل از به پایان رساندن این فصل، قصد داریم بیشتر عملگرهای باقی مانده را معرفی کنیم. سایر عملگرهای جاوا اسکریپت نیز در فصل‌های بعدی و در زمان مناسب معرفی خواهند شد. در این بخش به معرفی عملگرهای منطقی (Logical Operators) می‌پردازیم که از پرکاربردترین عملگرها در برنامه‌نویسی هستند. البته کاربرد عملی این عملگرها را بیشتر در فصل بعد خواهید دید.

 

عملگر منطقی NOT (!)

این عملگر، ارزش منطقی عملوند خود را معکوس می‌کند. یعنی اگر مقدار عملوند true باشد، مقدار false را بازمی‌گرداند و اگر مقدار عملوند false باشد، مقدار true بازگردانده می‌شود. همچنین اگر مقدار عملوند true یا false نباشد، ابتدا طبق قوانینی که در بخش قبلی در مورد تابع Boolean اشاره شد، مقدار آن به true یا false تبدیل می‌شود. سپس عمل معکوس کردن ارزش منطقی انجام می‌شود. نمونه‌هایی از عملکرد این عملگر را در قطعه کد زیر مشاهده می‌کنید.


!true;
← false
!false;
← true
!null;
← true
!"Hello";
← false

توجه کنید که عملگر NOT، مانند عملگرهای "++" و "--" یک عملگر یگانی است. اما بر خلاف این عملگرها، عملگر NOT همیشه باید قبل از عملوند خود ظاهر شود و نمی‌تواند بعد از آن (در سمت راست عملوند) قرار گیرد.

 

عملگر منطقی AND (&&)

این عملگر نیز معمولاً به همراه داده‌های Boolean به کار برده می‌شود. این عملگر دارای دو عملوند است و مقدار بازگشتی از این عملگر در صورتی دارای ارزش true خواهد بود که، ارزش منطقی هر دو عملوند آن true باشد. در غیر این صورت ارزش منطقی مقدار بازگشتی false خواهد بود. به قطعه کد زیر توجه کنید.


true && false;
← false
false && true;
← false
true && true;
← true
true && !true;
← false
"Hello" && 0;
← 0

به آخرین دستور موجود در قطعه کد فوق توجه کنید. همانطور که مشاهده می‌کنید، خروجی این دستور true یا false نیست. اما از نظر ارزش منطقی، 0 برابر با false است. اگر دو عملوند عملگر AND را در همین دستور به معادل منطقی تبدیل کنید. عملوند اول معادل true و عملوند دوم معادل false است. در نتیجه، خروجی این عملگر باید دارای ارزش false باشد. که همینطور هم هست. زیرا عدد 0 دارای ارزش منطقی false است. پس یک بار دیگر عملکرد عملگر AND را به طور دقیق بیان می‌کنیم. "خروجی این عملگر در صورتی دارای ارزش منطقی true است که هر دو عملوند آن دارای ارزش منطقی true باشند. در غیر این صورت، خروجی آن دارای ارزش منطقی false است." اما این که چه زمانی خروجی این عملگر دارای نوع Boolean است و چه زمانی از نوع دیگری است، در انتهای همین بخش تشریح خواهد شد.

همچنین توجه کنید که عملگر AND را می‌توان برای هر تعداد عملوند دلخواه به کار برد. در این حالت، خروجی عملگر اول به عنوان عملوند اول عملگر دوم به کار برده می‌شود و ... . در نتیجه خروجی چنین ترکیباتی زمانی دارای ارزش منطقی true خواهد بود که تمام عملوندها دارای ارزش منطقی true باشند. در غیر این صورت خروجی کل ترکیب false خواهد بود. نمونه‌هایی از این نوع کاربرد عملگر AND را در قطعه کد زیر می‌توان مشاهده کرد.


true && false && false;
← false
true && true && true && true && false;
← false
true && true && true && true;
← true
 

عملگر منطقی OR (||)

این عملگر نیز مانند عملگر AND دو عملوند دارد. خروجی این عملگر زمانی دارای ارزش منطقی false خواهد بود که هر دو عملوند آن دارای ارزش false باشند. در غیر این صورت خروجی دارای ارزش منطقی true است. به قطعه کد زیر توجه کنید.


true || false;
← true
true || true;
← true
false || false;
← false
"Hello" || 0;
← "Hello"

باز هم مشاهده می‌کنید که مانند قطعه کد قبلی، اینجا نیز نتیجه‌ی آخرین دستور از نوع Boolean نیست و از نوع رشته‌ای است. پس اینجا هم فقط می‌توان گفت که "ارزش منطقی خروجی این عملگر در صورتی false است که ارزش منطقی هر دو عملوند آن false باشد. در غیر این صورت ارزش منطقی خروجی true خواهد بود." اما اینجا هم نوع داده‌ی خروجی با توجه به نوع داده‌ی ورودی می‌تواند متفاوت باشد.

عملگر OR را نیز می‌توان مانند عملگر AND به صورت زنجیره‌ای و برای تعداد دلخواهی از عملوند‌ها به کار برد. در این صورت، خروجی کل ترکیب، زمانی false خواهد بود که تمام عملوندها دارای ارزش منطقی false باشند. در غیر این صورت ارزش منطقی خروجی true خواهد بود. در قطعه کد زیر مواردی از این نوع استفاده از عملگر OR را مشاهده می‌کنید.


true || false || false || true || false;
← true
true || true || true;
← true
false || false || false || false;
← false
"Hello" || 0 || false || true;
← "Hello"
 

ارزیابی کمینه (Minimal Evaluation)

فرض کنید شرایط عمومی استخدام در یک شرکت به شرح زیر است :

متقاضیان استخدام برای مصاحبه به شما مراجعه می‌کنند. و شرایط به گونه‌ای است که هر متقاضی فقط در صورتی می‌تواند استخدام شود که دارای تمام شرایط فوق باشد و حتی اگر یکی از شروط رعایت نشود امکان استخدام وجود ندارد.

این شرایط، عملگر AND را در ذهن تداعی می‌کند. چرا که می‌توان ۳ شرط فوق را با عملگر AND با هم ترکیب کرد. در این صورت هر فرد فقط در صورتی استخدام خواهد شد (خروجی true) که پاسخش به هر ۳ سوال فوق مثبت (مقدار true) باشد. در غیر این صورت مردود (خروجی false) خواهد شد.

حال فرض کنید یک متقاضی به شما مراجعه می‌کند و شما سوال اول را می‌پرسید. اگر پاسخ متقاضی به سوال اول منفی باشد (نداشتن مدرک لیسانس)، آیا نیازی به پرسیدن سوالات بعدی هست؟ مسلماً خیر. زیرا مثبت یا منفی بودن پاسخ متقاضی به سوالات بعدی، تاثیری در نتیجه‌ی نهایی ندارد و در هر صورت مردود خواهد شد.

در نتیجه در چنین شرایطی برای بالا بردن سرعت کار، هر مصاحبه‌گر هوشمندی باید از پرسیدن سوالات بعدی خودداری کند و به سراغ متقاضی بعدی برود. در برنامه‌نویسی نیز دقیقاً از این روش استفاده می‌شود. به قطعه کد زیر توجه کنید.


true && true && false && true && true;
← false

خروجی دستور فوق مقدار false است. اما آیا لازم است که مفسر جاوا اسکریپت برای رسیدن به این نتیجه تمام ۵ عملوند فوق را بررسی کند؟ پاسخ منفی است. زیرا با رسیدن به عملوند سوم و دیدن مقدار false، مفسر به این نتیجه می‌رسد که خروجی در هر صورت دارای ارزش منطقی false خواهد بود و نیازی به ارزیابی سایر عملوندها نیست. لذا جهت افزایش سرعت اجرای برنامه، از بررسی سایر عملوندها صرف نظر کرده و مقدار false را بازمی‌گرداند. امروزه این تکنیک در اکثر زبان‌های برنامه‌نویسی به کار برده می‌شود و چندین نام مختلف برای آن به کار برده می‌شود. از جمله ارزیابی اتصال کوتاه یا مدار کوتاه (Short-circuit Evaluationارزیابی تنبل (Lazy Evaluation) و ارزیابی کمینه (Minimal Evaluation). در این کتاب استفاده از اصطلاح ارزیابی کمینه ترجیح داده شده است.

همین تکنیک در مورد عملگر OR نیز به شکل دیگری به کار برده می‌شود. می‌دانیم که خروجی این عملگر زمانی false است که تمام عملوندهای آن false باشند و اگر فقط یک مقدار true در عملوندها موجود باشد، نتیجه true خواهد بود. لذا اینجا نیز می‌توان از ارزیابی کمینه استفاده کرد و با رسیدن به اولین عملوندی که مقدار true دارد، از ارزیابی سایر عملوندها صرف نظر کرده و مقدار true را به خروجی فرستاد. مثلاً در قطعه کد زیر، در دستور اول فقط یک عملوند و در دستور دوم فقط دو عملوند اول ارزیابی می‌شوند.


true || false;
← true
false || true || true || false;
← true

اما تنها نکته‌ی باقی مانده از این مبحث این است که چرا خروجی عملگرهای OR و AND در برخی مواقع از نوع Boolean و در برخی مواقع از انواع دیگر است؟ در واقع در جاوا اسکریپت مقدار خروجی این عملگرها، همیشه برابر با آخرین عملوندی است که ارزیابی می‌کنند. مثلاً در دو دستور فوق، آخرین مقدار ارزیابی شده مقدار true بوده، در نتیجه همین مقدار بازگردانده شده است. حال اگر دستورات فوق را به شکل زیر تغییر دهیم، خروجی‌ها نیز تغییر خواهند کرد. (دقت کنید که از نظر ارزش منطقی هیچ تغییری ایجاد نشده است.)


"Hello" || false;
← "Hello"
false || 11 || true || false;
← 11

به عبارت دیگر در هر نقطه‌ای که خروجی یک عبارت منطقی مشخص شود، به طوری که دیگر احتیاجی به ارزیابی سایر عملوندها نباشد. مقدار همان عملوندی که موجب تعیین قطعی مقدار خروجی شده است، بازگردانده می‌شود. اگر هم چنین اتفاقی رخ ندهد و برای رسیدن به نتیجه، مجبور به ارزیابی تمام عملوندها باشیم، دقیقاً آخرین عملوند بازگردانده می‌شود. در قطعه کد زیر نیز چندین نمونه از چنین رفتارهایی را مشاهده می‌کنید.


false || "Hello";
← "Hello"
true || "Hello";
← true
true && "Hello" && 0 && 11;
← 0
false && 123;
← false
true && 123;
← 123

همچنین توجه کنید که نتیجه‌ی عملگرهای AND و OR را می‌توان مجدداً با یکدیگر ترکیب کرد (با عملگر AND یا OR). در فصول بعدی چنین مواردی را بیشتر مشاهده خواهید کرد. قطعه کد زیر یک نمونه از چنین کاربردی را نمایش می‌دهد.


(false || "Hello") && (false || true || false);
← true

در دستور فوق، نتیجه‌ی ارزیابی پرانتز اول برابر با "Hello" و نتیجه‌ی ارزیابی پرانتز دوم برابر با true خواهد بود. حال اگر این دو مقدار را با همین ترتیب به عملگر AND اعمال کنیم. خروجی این عملگر طبق مباحث مطرح شده true خواهد بود.