مسیرها
/
JavaScript
JavaScript
/
تمرین‌ها
/
استاد لازانیا
استاد لازانیا

استاد لازانیا

تمرین یادگیری

مقدمه

«تابع» بلوکی از کد سازمان‌یافته و قابل‌استفاده‌ی مجدد است که برای انجام کاری به کار می‌رود. در JavaScript چندین روش برای تعریف تابع وجود دارد. در اینجا «اعلان تابع» و «عبارت تابع» را بررسی می‌کنیم. امکان‌های دیگری مانند توابع پیکانی در مفاهیم دیگر بررسی می‌شوند.

اعلان تابع

روش استاندارد تعریف تابع در JavaScript، اعلان تابع است که به آن تعریف تابع یا دستور تابع هم می‌گویند.

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

function someName(param1, param2, param3) {
  // ...
}

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

someName(arg1, arg2, arg3);

پارامترها

هنگام کار با پارامترها در بدنه‌ی تابع، مراقب «اثرهای جانبی» احتمالی باشید.

  • مقدارهای انواع داده‌های اولیه «تغییرناپذیر» هستند. مقدار اصلی هرگز از آنچه در بدنه‌ی تابع بر سر آرگومان می‌آید تأثیر نمی‌گیرد.
  • برای همه‌ی مقدارهای دیگر (شیءها، آرایه‌ها، توابع)، انتساب دوباره بر مقدار اصلی تأثیری ندارد. اما اگر چنین آرگومانی را تغییر بدهید (مثلاً کلیدی به یک شیء اضافه کنید)، مقدار اصلی‌ای هم که پاس داده شده بود تغییر می‌کند.

به‌طور پیش‌فرض، همه‌ی پارامترهایی که در اعلان تابع تعریف می‌شوند در JavaScript اختیاری‌اند. اگر آرگومان‌های کمتری از تعداد پارامترها بدهید، آرگومان‌های جاافتاده درون تابع undefined خواهند بود؛ به Null و Undefined نگاه کنید. در بسیاری از موارد، منطقی است که مقدار پیش‌فرض مناسب‌تری به‌جای undefined در نظر بگیریم. این کار با مشخص کردن «پارامترهای پیش‌فرض» به‌طور مستقیم در تعریف تابع انجام می‌شود.

function someName(param1 = defaultValue1, param2 = defaultValue2) {
  // ...
}

دستور return

یک دستور return اجرای تابع را پایان می‌دهد و مقداری را تعیین می‌کند که باید به فراخواننده‌ی تابع برگردانده شود. یک تابع می‌تواند چندین دستور return داشته باشد.

function checkNumber(num) {
  if (num === 0) {
    return 'You passed 0, please provide another number.';
  }

  return 'Thanks for passing such a nice number.';
}

مقدار بازگشتی یک تابع را می‌توان در یک متغیر ذخیره کرد.

function sum(x, y) {
  return x + y;
}

const total = sum(5, 10);
// => 15

نتیجه‌ی تابعی که مقداری را return نمی‌کند یا دستور return ندارد، undefined است. در JavaScript هیچ return ضمنی وجود ندارد.

function nakedReturn(a) {
  a * 2;
  return;
}

nakedReturn(1);
// => undefined

function noReturn(a) {
  a * 2;
}

noReturn(1);
// => undefined

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

function divide(a, b) {
  return {
    quotient: Math.floor(a / b),
    remainder: a % b,
  };
}

عبارت تابع

اعلان تابع یک دستور مستقل است. اما گاهی کمک‌کننده است که تابع را به‌عنوان بخشی از یک عبارت دیگر تعریف کنید، مثلاً در یک انتساب، به‌عنوان پارامتر یک تابع (تابع فراخوان) یا به‌عنوان مقداری در یک شیء. این کار با یک عبارت تابع انجام می‌شود. نحوه‌ی نگارش آن مانند اعلان تابع است، فقط با این تفاوت که می‌توان اسم تابع را حذف کرد تا یک «تابع بی‌نام» ساخت.

const someFunction = function (param) {
  // ...
};

someOtherFunction(function (param) {
  // ...
});

const obj = {
  someFunction: function (param) {
    // ...
  },
};

دستورالعمل‌ها

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

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

1. مشخص کنید لازانیا پخته شده است یا نه

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

تابعی به اسم cookingStatus بنویسید که زمان باقی‌مانده‌ی تایمر را بر حسب دقیقه به عنوان پارامتر می‌پذیرد. این تابع سه نتیجه‌ی ممکن دارد.

  • اگر تایمر 0 را نشان دهد، باید 'Lasagna is done.' را برگرداند.
  • اگر تایمر هر عدد دیگری را نشان دهد، نتیجه باید 'Not done, please wait.' باشد.
  • اگر تابع بدون مقدار تایمر فراخوانی شود، نتیجه باید 'You forgot to set the timer.' باشد.

تایمر هرگز مقداری کمتر از ۰ نشان نمی‌دهد.

cookingStatus(12);
// => 'Not done, please wait.'

cookingStatus();
// => 'You forgot to set the timer.'

2. زمان آماده‌سازی را تخمین بزنید

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

تابعی به اسم preparationTime پیاده‌سازی کنید که یک آرایه از لایه‌ها و میانگین زمان آماده‌سازی هر لایه را بر حسب دقیقه می‌پذیرد. تابع باید برآورد کل زمان آماده‌سازی را بر اساس تعداد لایه‌ها برگرداند. اگر تابع بدون ارائه‌ی میانگین زمان آماده‌سازی فراخوانی شود، به جایش باید 2 دقیقه در نظر گرفته شود.

const layers = ['sauce', 'noodles', 'sauce', 'meat', 'mozzarella', 'noodles'];
preparationTime(layers, 3);
// => 18

preparationTime(layers);
// => 12

3. مقدار رشته و سس لازم را محاسبه کنید

علاوه بر کنار گذاشتن زمان، می‌خواهید مطمئن شوید سس و رشته‌ی کافی برای پختن لازانیای رؤیایی‌تان دارید. برای هر لایه‌ی رشته در لازانیایتان به ۵۰ گرم رشته نیاز دارید. برای هر لایه‌ی سس در لازانیایتان به ۰٫۲ لیتر سس نیاز دارید.

تابعی به اسم quantities تعریف کنید که یک آرایه از لایه‌ها را به عنوان پارامتر می‌گیرد. سپس تابع مقدار رشته و سس لازم برای پختن غذایتان را تعیین می‌کند. نتیجه باید به صورت یک شیء با کلیدهای noodles و sauce برگردانده شود.

quantities(['sauce', 'noodles', 'sauce', 'meat', 'mozzarella', 'noodles']);
// => { noodles: 100, sauce: 0.4 }

4. ماده‌ی اولیه‌ی مخفی را اضافه کنید

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

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

const friendsList = ['noodles', 'sauce', 'mozzarella', 'kampot pepper'];
const myList = ['noodles', 'meat', 'sauce', 'mozzarella'];

addSecretIngredient(friendsList, myList);
// => undefined

console.log(myList);
// => ['noodles', 'meat', 'sauce', 'mozzarella', 'kampot pepper']

5. دستور پخت را مقیاس‌بندی کنید

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

تابعی به اسم scaleRecipe پیاده‌سازی کنید که دو پارامتر می‌گیرد.

  • یک شیء دستور پخت که مقدارهای لازم برای ۲ وعده را در خود دارد. قالب این شیء را در مثال زیر می‌بینید.
  • تعداد وعده‌هایی که می‌خواهید بپزید.

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

const recipe = {
  noodles: 200,
  sauce: 0.5,
  mozzarella: 1,
  meat: 100,
};

scaleRecipe(recipe, 4);
// =>
// {
//   noodles: 400,
//   sauce: 1,
//   mozzarella: 2,
//   meat: 200,
// };

console.log(recipe);
// =>
// {
//   noodles: 200,
//   sauce: 0.5,
//   mozzarella: 1,
//   meat: 100,
// };
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
JavaScript Exercism

آماده‌اید استاد لازانیا را شروع کنید؟

در Exercism ثبت‌نام کنید تا JavaScript را همراه با 37 مفهوم159 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.