مقداردهی پیش‌فرض و جمع‌آوری آرگومان‌ها با Default و Rest Parameters

اهداف یادگیری

  • یادگیری نحوه‌ی تعیین مقدار پیش‌فرض برای پارامترها
  • درک اینکه Default Parameter دقیقاً در چه شرایطی فعال می‌شود
  • آشنایی با Rest Parameters برای جمع‌آوری تعداد نامشخصی آرگومان
  • فهم تفاوت Rest Parameters با Spread Operator که پیش‌تر دیدیم

مقدمه

در درس‌های قبل دیدیم که اگر آرگومانی برای یک پارامتر ارسال نشود، مقدار آن پارامتر به‌طور خودکار undefined می‌شود. همچنین دیدیم که اگر آرگومان بیشتری نسبت به پارامترها ارسال شود، آرگومان‌های اضافی نادیده گرفته می‌شوند. در این درس، دو ابزار مهم را یاد می‌گیریم که کنترل بیشتری روی این دو موقعیت به ما می‌دهند: Default Parameters و Rest Parameters.

Default Parameters — مقدار پیش‌فرض پارامتر

گاهی می‌خواهیم اگر آرگومانی برای یک پارامتر ارسال نشد، به‌جای undefined، یک مقدار پیش‌فرض مشخص در نظر گرفته شود:

استفاده از Default Parameter
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل کد

وقتی greet("علی") فراخوانی می‌شود، چون آرگومانی ارسال شده، همان مقدار "علی" استفاده می‌شود و مقدار پیش‌فرض نادیده گرفته می‌شود. اما وقتی greet() بدون هیچ آرگومانی فراخوانی می‌شود، چون مقدار name برابر undefined است، جاوااسکریپت به‌طور خودکار مقدار پیش‌فرض "کاربر مهمان" را جایگزین می‌کند.

نکته‌ی مهم: Default Parameter فقط برای undefined فعال می‌شود

یک نکته‌ی ظریف اما مهم این است که مقدار پیش‌فرض، فقط زمانی فعال می‌شود که آرگومان دقیقاً undefined باشد؛ نه هر مقدار Falsy دیگری:

Default Parameter فقط با undefined فعال می‌شود
خروجی کنسول اینجا نمایش داده می‌شود...

همان‌طور که مشاهده می‌کنید، حتی مقادیر Falsy مثل null، "" یا 0 باعث فعال شدن مقدار پیش‌فرض نمی‌شوند؛ فقط undefined (یا نبودِ کامل آرگومان که خودش معادل undefined است) این اتفاق را رقم می‌زند.

مقدار پیش‌فرض بر اساس پارامتر دیگر

مقدار پیش‌فرض یک پارامتر می‌تواند به پارامترهای قبلی هم وابسته باشد:

function createBox(width, height = width) {
  console.log(width + " x " + height);
}

createBox(10);     // 10 x 10
createBox(10, 20); // 10 x 20

Rest Parameters — جمع‌آوری تعداد نامشخص آرگومان

گاهی نمی‌دانیم دقیقاً چند آرگومان به تابع ارسال خواهد شد. برای این موقعیت، از Rest Parameters استفاده می‌کنیم که با سه‌نقطه (...) قبل از نام پارامتر مشخص می‌شود:

جمع‌آوری آرگومان‌ها با Rest Parameter
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل کد

در این مثال، ...numbers تمام آرگومان‌های ارسال‌شده را به‌صورت یک آرایه‌ی واقعی در متغیر numbers جمع‌آوری می‌کند؛ صرف‌نظر از اینکه چند آرگومان ارسال شده باشد. به همین دلیل می‌توانیم بدون مشکل از حلقه‌ی for...of و متدهای آرایه روی آن استفاده کنیم.

ترکیب پارامترهای معمولی با Rest Parameter

Rest Parameter می‌تواند در کنار پارامترهای معمولی هم استفاده شود، اما با یک قانون مهم: باید همیشه آخرین پارامتر باشد:

function introduce(firstName, lastName, ...hobbies) {
  console.log(firstName, lastName);
  console.log(hobbies);
}

introduce("علی", "رضایی", "فوتبال", "شنا", "کتاب‌خوانی");
// علی رضایی
// ["فوتبال", "شنا", "کتاب‌خوانی"]

اگر Rest Parameter در وسط لیست پارامترها قرار بگیرد، جاوااسکریپت خطای Syntax می‌دهد؛ چون معنایی برای پارامترهای بعد از آن وجود نخواهد داشت.

تفاوت Rest Parameters با Spread Operator

در درس‌های قبل با Spread Operator (...) برای کپی کردن Object و Array آشنا شدیم. Rest Parameter از همین نماد ... استفاده می‌کند، اما نقش آن دقیقاً برعکس Spread است:

ویژگیSpread OperatorRest Parameter
کجا استفاده می‌شودهنگام فراخوانی تابع یا ساخت Array/Objectهنگام تعریف پارامترهای تابع
عملکردیک مجموعه را باز می‌کند (Expand)چند مقدار را جمع می‌کند (Collect)
// Spread — باز کردن آرایه
let numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3

// Rest — جمع کردن آرگومان‌ها
function sum(...nums) {
  console.log(nums); // [1, 2, 3]
}
sum(1, 2, 3);

اشتباهات رایج

  • تصور اینکه هر مقدار Falsy باعث فعال شدن Default Parameter می‌شود؛ درحالی‌که فقط undefined این اثر را دارد.
  • قرار دادن Rest Parameter در جایی غیر از انتهای لیست پارامترها.
  • خلط کردن Rest Parameter با Spread Operator، چون هر دو از نماد یکسانی استفاده می‌کنند.

Best Practices

  • برای پارامترهایی که معمولاً مقدار ثابت و رایجی دارند، از Default Parameter استفاده کنید تا فراخوانی تابع ساده‌تر شود.
  • وقتی تعداد آرگومان‌های ورودی تابع از قبل مشخص نیست، از Rest Parameter به‌جای دستکاری دستی آرگومان‌ها استفاده کنید.

ارتباط با سایر مفاهیم

Rest Parameter در واقع همیشه یک آرایه‌ی واقعی می‌سازد، برخلاف شیء شبه‌آرایه‌ای قدیمی‌تر به نام arguments که در توابع معمولی وجود دارد؛ این تفاوت در فصل‌های بعدی، هنگام مقایسه‌ی Arrow Function و Function معمولی، بیشتر بررسی خواهد شد. Spread Operator نیز که در فصل آرایه‌ها دیدیم، از نظر ظاهری مشابه Rest است اما کاربرد کاملاً متفاوتی دارد.

جمع‌بندی

Default Parameters به ما اجازه می‌دهند برای پارامترها مقدار پیش‌فرض تعیین کنیم؛ این مقدار فقط زمانی فعال می‌شود که آرگومان دقیقاً undefined باشد. Rest Parameters با استفاده از ... پیش از نام پارامتر، تعداد نامشخصی از آرگومان‌ها را به‌صورت یک آرایه‌ی واقعی جمع‌آوری می‌کنند و همیشه باید آخرین پارامتر تابع باشند.