۱۳ ژوئیه ۲۰۲۳

دستور "switch"

یک دستور ‍‍switch می‌تواند جایگزین چند if پشت سر هم بشود.

این دستور توصیف یک متغیر که می‌تواند چند مقدار داشته باشد را راحت‌تر می‌کند.

The syntax

یک دستور switch یک یا چند بلوک case دارد و می‌توان برای آن یک مقدار اختیاری پیش‌فرض تعریف کرد.

و بدین شکل نوشته می‌شود:

switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
  • در این مرحله چک می‌شود که مقدار x دقیقا با مقدار case اول برابر باشد. که اینجا مقدار آن value1 است. سپس برابر بودن آن با (value2) چک می‌شود و به همین ترتیب ادامه پیدا می‌کند.
  • اگر مقدار برابری پیدا کند، switch، کد داخل case مورد نظر را اجرا می‌کند. و تا زمانی که به نزدیک‌ترین break برسد یا به پایان switch برسد این کار را ادامه می‌دهد.
  • اگر با هیچ‌کدام از caseها جور نشود، کد default اجرا می‌شود. البته اگر وجود داشته باشد.

یک مثال

یک مثال از دستور switch (کد اجرا شده هایلایت شده است):

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
    break;
  case 4:
    alert("Exactly!");
    break;
  case 5:
    alert( 'Too big' );
    break;
  default:
    alert( "I don't know such values" );
}

در اینجا دستور switch با مقایسه‌ی a با case اول شروع می‌کند. که در اینجا مقدار آن 3 است و تطابق ندارند.

سپس به سراغ 4 می‌رود. این یکی برابر است و تطابق پیدا می‌کند. پس اجرای کد از case 4 شروع می‌شود و تا نزدیک‌ترین break ادامه می‌یابد.

اگر break وجود نداشته باشد، caseهای بعدی هم اجرا می‌شوند.

یک مثال بدون break:

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
  case 4:
    alert( 'Exactly!' );
  case 5:
    alert( 'Too big' );
  default:
    alert( "I don't know such values" );
}

در مثال بالا هر سه alert به‌ترتیب اجرا خواهند شد:

alert('Exactly!');
alert('Too big');
alert("I don't know such values");
هر عبارتی می‌تواند به یک switch/case تبدیل شود

هم در switch و هم در case می‌توان از عبارت‌های قراردادی استفاده کرد.

برای مثال:

let a = "1";
let b = 0;

switch (+a) {
  case b + 1:
    alert("this runs, because +a is 1, exactly equals b+1");
    break;

  default:
    alert("this doesn't run");
}

در اینجا a+ برابر با 1 است و وقتی با b + 1 در case مقایسه می‌شود، کد متناظر اجرا می‌شود.

گروه‌بندی “case”

چند case مختلف که یک کد دارند، می‌تواند با هم قرار بگیرند.

برای مثال اگر می‌خواهیم یک کد یکسان برای case 3 و case 5 اجرا شود:

let a = 3;

switch (a) {
  case 4:
    alert('Right!');
    break;

  case 3: // (*) grouped two cases
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;

  default:
    alert('The result is strange. Really.');
}

حالا 3 و 5 پیام یکسانی نمایش می‌دهند.

این توانایی که می‌توان caseهای مختلف را گروه‌بندی کرد، به این خاطر است که switch/case چگونه بدون break کار می‌کند. اینجا اجرای کد case 3 از خط (*) شروع می‌شود و تا خط case 5 ادامه پیدا می‌کند. چرا که هیچ break وجود ندارد.

نوع داده مهم است

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

برای مثال کد زیر را در نظر بگیرید:

let arg = prompt("Enter a value?");
switch (arg) {
  case '0':
  case '1':
    alert( 'One or zero' );
    break;

  case '2':
    alert( 'Two' );
    break;

  case 3:
    alert( 'Never executes!' );
    break;
  default:
    alert( 'An unknown value' )
}
  1. برای 0 و 1 اولین alert اجرا می‌شود.
  2. برای 2 دومین alert اجرا می‌شود.
  3. ولی برای 3 مقدار prompt یک string است و "3" با 3 با === برابر نیست. یعنی در case 3 یک کد مرده داریم. و به‌همین دلیل default اجرا می‌شود.

تمارین

اهمیت: 5

کد زیر را با استفاده از if..else بازنویسی کنید

switch (browser) {
  case 'Edge':
    alert("You've got the Edge!");
    break;

  case 'Chrome':
  case 'Firefox':
  case 'Safari':
  case 'Opera':
    alert('Okay we support these browsers too');
    break;

  default:
    alert('We hope that this page looks ok!');
}

برای این که یک if دقیقا مانند switch عمل کند باید از مقایسه '===' استفاده کند:

برای stringها یک مساوی معمولی '==' هم کفایت می‌کند

if (browser == 'Edge') {
  alert("You've got the Edge!");
} else if (
  browser == 'Chrome' ||
  browser == 'Firefox' ||
  browser == 'Safari' ||
  browser == 'Opera'
) {
  alert('Okay we support these browsers too');
} else {
  alert('We hope that this page looks ok!');
}

دقت داشته باشید که این کدها 'browser == 'Chrome' || browser == 'Firefox … برای خوانایی بیشتر به چند خط تقسیم شده‌اند:

ولی switch تمیزتر و بهتر است.

اهمیت: 4

کد زیر را با استفاده از فقط یک switch بازنویسی کنید:

let a = +prompt('a?', '');

if (a == 0) {
  alert(0);
}
if (a == 1) {
  alert(1);
}

if (a == 2 || a == 3) {
  alert('2,3');
}

دو چک اول به دو case تبدیل می‌شوند. و چک سوم به دو case تقسیم می‌شود:

let a = +prompt('a?', '');

switch (a) {
  case 0:
    alert( 0 );
    break;

  case 1:
    alert( 1 );
    break;

  case 2:
  case 3:
    alert( '2,3' );
    break;
}

دقت داشته باشید: break که در انتها آمده ضروری نیست ولی آن را برای این می‌گذاریم که کدمان در آینده درست کار کند…

ممکن است بخواهیم در آینده case های بیشتری اضافه کنیم؛ برای مثال case 4. در این صورت اگر فراموش می‌کنم که قبل از آن در case 3 یک break بگذاریم به مشکل برمی‌خوریم. و ارور دریافت می‌کنیم. برای همین است که این break آخری را می‌گذاریم.

نقشه آموزش