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

ساختار شرطی if-else

در دو فصل گذشته با مبانی برنامه نویسی با زبان جاوا اسکریپت آشنا شدید. در این فصل پا را کمی فراتر گذاشته و با برخی از مهمترین مفاهیم در برنامه‌نویسی (با هر زبانی)، آشنا می‌شویم.

از مهمترین مباحث مورد بحث در این فصل می‌توان به موارد زیر اشاره کرد :  

ساختارهای شرطی

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

سوال این است که برنامه‌ی شما چطور باید تصمیم بگیرد که کدام پیغام را نمایش دهد؟ این در واقع همان کاری است که با ساختارهای شرطی یا ساختارهای تصمیم‌گیری در جاوا اسکریپت (و سایر زبان‌های برنامه‌نویسی) انجام می‌شود. انوع مختلفی از ساختارهای تصمیم در جاوا اسکریپت وجود دارد که در این بخش به بررسی برخی از آنها می‌پردازیم.

 

ساختار شرطی if

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


if (condition) {
       // دستورات اجرایی در صورت صحیح بودن شرط
}

به ساختار فوق کمی با دقت توجه کنید. در این ساختار ابتدا کلمه‌ی کلیدی if و بعد از آن یک پرانتز باز و بسته قرار می‌گیرد. داخل این پرانتز باید یک شرط (condition) را مشخص کنید که در صورتی که مقدار آن (یا نتیجه‌ی آن) برابر با true باشد. آنگاه کلیه‌ی دستوراتی که داخل آکلادهای باز و بسته قرار گرفته‌اند اجرا خواهند شد. در غیر این صورت از تمامی این دستورات صرف نظر شده و اجرا نخواهند شد. مثلاً در قطعه کد زیر، در صورتی که مقدار متغیر a بزرگتر از ۴ باشد، دستورات داخل آکلاد اجرا خواهند شد.


if (a > 4) {
       console.log('The value is greater than 4');
}

توجه کنید که عبارت داخل پرانتز که به عنوان شرط به کار برده می‌شود. می‌تواند هر نوع عبارت محاسباتی، مقایسه‌ای، انتسابی و یا حتی یک متغیر یا ثابت باشد. هر عبارتی که به عنوان شرط به کار برده شود. ابتدا ارزیابی شده و مقدار نهایی آن بررسی می‌شود. اگر مقدار نهایی از نوع Boolean باشد، نیاز به تبدیل خاصی نیست و در صورتی که مقدار نهایی true باشد، دستورات اجرا می‌شوند. اما اگر مقدار نهایی از نوعی دیگر باشد، ابتدا به صورت ضمنی، طبق قوانینی که در فصل قبل بررسی شد به معادل Boolean تبدیل می‌شود. سپس تصمیم‌گیری بر اساس مقدار Boolean به دست آمده انجام می‌شود. مثلاً در قطعه کد زیر، ابتدا عبارت محاسباتی "۴ - ۲" ارزیابی می‌شود. و با توجه به اینکه نتیجه‌ی آن مقدار عددی ۲ است. این مقدار به صورت ضمنی به مقدار Boolean تبدیل می‌شود. که با توجه به قوانینی که پیش‌تر بررسی شد این مقدار عددی به مقدار true تبدیل می‌شود. لذا کل دستورات داخل آکلاد اجرا می‌شوند.


if (4 - 2) {
       // دستوراتی که در این قسمت قرار دارند حتماً اجرا می‌شوند. زیرا مقدار 2 از نظر ارزش منطقی صحیح است
}

هرچند در قسمت condition هر نوع عبارتی را می‌توان به کار برد. اما معمولاً در این قسمت از عبارات مقایسه‌ای استفاده می‌شود.

نکته : به دستوراتی که داخل آکلاد باز و بسته "{}" قرار می‌گیرند، اصطلاحا یک "بلاک کد" گفته می‌شود. یک بلاک کد می‌تواند شامل هر تعداد دستور، یا انواع ساختارهای مختلف برنامه‌نویسی باشد. در ساختار شرطی if، در صورتی که فقط یک دستور داخل بلاک کد وجود داشته باشد، می‌توان آکلادها را حذف کرد و از بلاک کد استفاده نکرد. مانند قطعه کد زیر.


if (a == 4)
       console.log('The value is : 4');

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

نکته : یکی از اشتباهات رایج در بین برنامه‌نویسان، استفاده از عملگر "="، به جای عملگر "==" یا "===" در زمان مقایسه‌ی مقدارها در ساختار شرطی if است. توجه کنید که اگر از عملگر "=" در قسمت شرط استفاده کنید. احتمالاً با نتایج غیر منتظره‌ای روبرو خواهید شد. زیرا این عملگر هیچ مقایسه‌ای انجام نمی‌دهد و فقط مقدار عملوند سمت راست را در عملوند سمت چپ (که باید یک متغیر باشد) قرار می‌دهد. مثلاً در قطعه کد زیر، بدون توجه به مقدار قبلی متغیر a که 0 است. نتیجه‌ی شرط همیشه true است. زیرا ابتدا مقدار عددی 4 در متغیر a قرار می‌گیرد. سپس این مقدار به عنوان نتیجه‌ی عبارت به مقدار Boolean تبدیل می‌شود. که برابر با true است. در نتیجه این شرط همیشه برقرار است و دستورات داخل آکلاد همیشه اجرا خواهند شد.


let a = 0;
if (a = 4) {
       console.log('The value is greater than 4');
}

پس لازم است در هنگام استفاده از عملگرهای مقایسه‌ای نکته‌ی فوق را مد نظر قرار دهید.

 

ساختار شرطی if , else

دیدیم که با استفاده از ساختار شرطی if می‌توان دستوراتی را فقط در صورت true بودن یک شرط (یا عبارت) اجرا کرد. اما گاهی اوقات لازم است تا در صورت false بودن آن شرط نیز دستورات دیگری اجرا شوند. در این مواقع می‌توان از ساختار شرطی if , else استفاده کرد. نحوه‌ی استفاده از این ساختار را در قطعه کد زیر می‌بینید.


if (condition) {
       // دستوراتی که در صورت صحیح بودن شرط اجرا می‌شوند
}else{
       // دستوراتی که در صورت غلط بودن شرط اجرا می‌شوند
}

در این ساختار، در صورتی که مقدار condition برابر با false باشد. دستوراتی که در بلاک کد دوم (بعد از کلمه‌ی کلیدی else) قرار دارند اجرا خواهند شد. به عنوان مثال در قطعه کد زیر، دستورات موجود در بلاک کد مربوط به else اجرا می‌شوند. چرا که مقدار متغیر a کوچتر از ۲۰ است.


let a = 19;
if (a > 20) {
      console.log('The value is greater than 20');
}else{
       console.log('The value is equal or less then 20');
}

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

حال سعی کنید در دستور اول، مقادیر مختلف عددی را به متغیر a نسبت دهید و نتیجه را در کنسول مشاهده کنید تا عملکرد ساختار if , else را بهتر درک کنید.  

ساختار if , else if , else

حال به سوال اول برمی‌گردیم. مسئله‌ی آزمون چهار گزینه‌ای را دوباره تصور کنید. آیا می‌توان چنین مسئله‌ای را با یک ساختار شرطی if یا یک ساختار شرطی if , else پیاده‌سازی کرد؟ پاسخ این سوال منفی است. زیرا در این ساختار‌ها فقط یک شرط بررسی می‌شود و شما می‌توانید دستوراتی را برای دو حالتی که نتیجه‌ی شرط true یا false باشد در نظر بگیرید. اما در مسئله‌ی ما ۴ حالت مختلف وجود دارد. در چنین شرایطی باید از ساختار if , else if , else استفاده کنیم. نحوه‌ی استفاده از این ساختار را در قطعه کد زیر مشاهده می‌کنید.


if (condition1) {
      // در صورتی که شرط اول صحیح باشد این دستورات اجرا می‌شوند
}else if(condition2){
      // در صورتی که شرط دوم صحیح باشد این دستورات اجرا می‌شوند
}else if(condition3){
      // در صورتی که شرط سوم صحیح باشد این دستورات اجرا می‌شوند
}else{
      // در صورتی که هیچ یک از شرط‌های فوق صحیح نباشند این دستورات اجرا می‌شوند
}

در این ساختار می‌توان به تعداد دلخواه شرط‌های مختلفی را به کار برد. شرط اول بعد از کلمه‌ی کلیدی if قرار می‌گیرد و در صورت true بودن این شرط، تمام دستورات موجود در بلاک اول اجرا می‌شوند. در غیر این صورت شرط دوم بررسی می‌شود و در صورت true بودن این شرط، دستورات موجود در بلاک دوم اجرا می‌شوند. در صورتی که این شرط هم false باشد، شرط سوم بررسی می‌شود و این روند به تعداد شرط‌های تعیین شده تکرار می‌شود. در نهایت اگر هیچ یک از شرط‌ها مقدار true نداشته باشند، دستورات موجود در بلاک آخر (مربوط به else) اجرا می‌شوند.

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

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


let trueAnswers = 10;
if (trueAnswers < 5) {
      console.log('خیلی ضعیف');
}else if(trueAnswers <= 10){
      console.log('ضعیف');
}else if(trueAnswers <= 15){
      console.log('متوسط');
}else{
      console.log('عالی');
}

این برنامه را نیز می‌توانید اینجا به صورت آنلاین در CodePen اجرا کنید. سعی کنید مقدار متغیر trueAnswers را تغییر دهید تا نتیجه را در حالت‌های مختلف مشاهده کنید.

به شرط‌های به کار رفته شده در کد فوق توجه کنید. نکته‌ای که پیش‌تر به آن اشاره کردیم در این مثال کاملاً مشهود است. مثلاً اگر مقدار متغیر trueAnswers برابر با ۱۰ باشد، همزمان شرط‌های دوم و سوم true هستند. ولی فقط بلاک کد مربوط به شرط دوم اجرا خواهد و از بلاک کد سوم صرف نظر خواهد شد.

اما قطعه کد فوق یک ایراد بسیار مهم دارد که عمداً در این کد قرار داده شده است تا اهمیت آن روشن شود. زمانی که شما با استفاده از ساختارهای شرطی، حالت‌های مختلف یک یا چند متغیر را بررسی می‌کنید. باید دقت کنید که ورودی‌های نامعتبر، اشکال یا ابهامی در خروجی به وجود نیاورند. مشکل کد فوق این است که در آن فرض شده است که مقدار ورودی (مقدار trueAnswers)، یک مقدار معتبر است. اما مقدار معتبر چیست؟

اگر صورت مسئله را دوباره مرور کنید، متوجه خواهید شد که در چنین مسئله‌ای، مقدار ورودی باید عددی بین ۰ تا ۲۰ باشد. حال اگر عددی کوچکتر از صفر، یا عددی بزرگتر از ۲۰ به عنوان ورودی به این برنامه داده شود. در این صورت نباید هیچ یک از پیغام‌های فوق به کاربر نمایش داده شود. بلکه باید پیغام خطایی نمایش داده شود تا کاربر (یا هر نرم‌افزای که این کد را اجرا می‌کند)، متوجه نامعتبر بودن ورودی شده و سعی در اصلاح آن کند.

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

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


let trueAnswers = -1;
if (trueAnswers >= 0 && trueAnswers < 5){
      console.log('خیلی ضعیف');
}else if(trueAnswers >= 5 && trueAnswers <= 10){
      console.log('ضعیف');
}else if(trueAnswers >= 11 && trueAnswers <= 15){
      console.log('متوسط');
}else if(trueAnswers > 15 && trueAnswers <= 20){
      console.log('عالی');
}else{
      console.log('مقدار ورودی نامعتبر است');
}

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

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

 

عملگر شرطی "?:"

ساختار if , else را بررسی کردیم و دیدید که کاربرد این ساختار زمانی است که بخواهیم برای هر دو حالت true و false بودن یک شرط، دستورات مجزایی را در نظر گرفته و اجرا کنیم. عملگر "?:" دقیقاً همین کار را انجام می‌دهد و هدف این عملگر خلاصه‌نویسی و کوتاه کردن کدهای برنامه است. این تنها عملگر جاوا اسکریپت است که ۳ عملوند دارد که به آن عملگر سه سه‌ای یا عملگر سه‌گانی (Ternary Operator) نیز گفته می‌شود. ساختار این عملگر را در قطعه کد زیر می‌بینید.


condition ? expression1 : expression2

در ساختار فوق، ابتدا شرط condition ارزیابی می‌شود. اگر مقدار آن true باشد expression1 و در غیر این صورت expression2 اجرا خواهد شد. توجه کنید که expression1 و expression2 می‌توانند هر نوع عبارت محاسباتی یا حتی یک متغیر یا ثابت یا یک مقدار لفظی (Literal) باشند که نتیجه‌ی این عبارات نیز توسط این ساختار بازگردانده شده و می‌توان از آن استفاده کرد. مثلاً در قطعه کد زیر از یک رشته‌ی لفظی به عنوان expression1 و expression2 استفاده شده است. در این صورت اگر مقدار شرط true باشد رشته‌ی اول و در غیر این صورت رشته‌ی دوم برگردانده می‌شود.


let age = 26;
let canRegister = (age > 18) ? "True, over 18" : "False, under 18";
console.log(canRegister);

در کد فوق با توجه به این که مقدار متغیر age بیشتر از ۱۸ است. شرط "age > 18" برقرار است. در نتیجه رشته‌ی "True , over 18" بازگردانده شده و در متغیر canRegister ذخیره می‌شود. سپس در خط بعدی این مقدار در کنسول چاپ می‌شود.