ورودی و خروجی در توابع
پارامترها و آرگومانها (Parameters and Arguments)
در بخش قبلی با مفاهیم اولیهی مربوط به توابع آشنا شدیم و چند تابع بسیار ساده را ایجاد کردیم که متن سادهای را در کنسول چاپ میکردند. اما توابعی که در عمل به کار برده میشوند معمولاً پیچیدهتر هستند و کاری بیش از چاپ یک متن ساده در کنسول را انجام میدهند.
در بسیاری از موارد، برای اینکه یک تابع عملکرد صحیحی داشته باشد، نیازمند دریافت یک یا چند مقدار ورودی است. به عنوان مثال همان تابع showBio که در بخش قبلی دیدیم را در نظر بگیرید. در این تابع مشخصات یک کاربر خاص در کنسول چاپ میشد. حال فرض کنید که به تابعی نیاز داریم که نام، نام خانوادگی و سن یک کاربر را دریافت کند. سپس مشخصات کاربر را با قالبی مشخص در کنسول چاپ کند. برای انجام این کار میتوان تابع showBio را به صورت زیر اصلاح کرد.
function showBio(firstname , lastname , age){
console.log("First name = " + firstname);
console.log("Last name = " + lastname);
console.log("Age = " + age);
}
همانطور که مشاهده میکنید در تعریف تابع فوق، پس از نام تابع و در داخل پرانتز از ۳ شناسه به عنوان ورودیهای این تابع استفاده شده است. این شناسهها را اصطلاحاً پارامترهای (Parameter) این تابع مینامند. حال در بدنهی تابع در هر نقطهی دلخواه میتوان از این شناسهها استفاده کرد. در این صورت مقدار ورودیهای ارسال شده به تابع برای هر یک از پارامترهای ورودی در محل مورد نظر جایگزین میشود. همانطور که میبیند در این تابع در هر یک از دستورات مقدار یکی از این پارامترهای ورودی چاپ شده است.
از این پس برای چاپ مشخصات هر کاربری، میتوان نام، نام خانوادگی و سن او را به این تابع ارسال کرد تا با قالبی که در این تابع مشخص شده است نمایش داده شود. به عنوان مثال میتوان تابع فوق را با مقادیر ورودی زیر فراخوانی کرد تا خروجی متناسب با آنها در کنسول نمایش داده شود.
showBio('Mohammad' , 'Moosavi' , 36);
← First name = Mohammad
← Last name = Moosavi
← Age = 36
و اگر با ورودیهای زیر این تابع را فراخوانی کنیم، خروجی متناسب با این ورودیها به صورت زیر در کنسول نمایش داده خواهند شد.
showBio('Ahmad' , 'Moosavi' , 33);
← First name = Ahmad
← Last name = Moosavi
← Age = 33
همانطور که مشاهده میکنید مقادیری که به عنوان ورودی به توابع ارسال میکنیم دقیقاً در مکانهای به کار رفته در بدنهی تابع جایگزین شدهاند. البته معمولاً در عمل کارهای پیچیدهتری با دادههای ورودی انجام میشود و این فقط یک مثال ساده از ارسال ورودی به یک تابع است.
به مقادیری که به عنوان ورودی به یک تابع ارسال میشوند (در مثال فوق Ahmad, Moosavi, 33) اصطلاحاً آرگومان (Argument) گفته میشود. به عبارت دیگر به شناسههایی که در زمان تعریف توابع در مقابل نام تابع قرار میگیرند پارامتر، و به مقادیری که برای هر یک از این شناسهها (که در داخل تابع به عنوان یک متغیر در دسترس هستند) ارسال میشود آرگومان گفته میشود.
همانطور که میبینید دو مفهوم پارامتر و آرگومان ارتباط بسیار نزدیکی با یکدیگر دارند و به همین دلیل معمولاً این اصطلاحات به جای یکدیگر نیز به کار برده میشوند و این جا به جایی حداقل در صحبتها و متون غیر رسمی بسیار مرسوم است.
توجه کنید که هیچ محدودیتی برای تعداد ورودیهای یک تابع وجود ندارد. یعنی به هر تعداد که نیاز باشد میتوانید برای یک تابع ورودی تعیین کنید. مثلاً تابع زیر ۵ ورودی عددی دریافت میکند و میانگین این اعداد را در کنسول چاپ میکند.
function mean(a , b , c , d , e){
let average , total;
total = a + b + c + d + e;
average = total / 5;
console.log("Average is : " + average);
}
حال میتوان تابع فوق را با ۵ آرگومان به صورت زیر فراخوانی کرده و میانگین اعداد را مشاهده کرد.
mean(2 , 4 , 10 , 11 , 4);
← Average is : 6.2
اگر تعداد آرگومانهای ورودی به یک تابع بیش از تعداد پارامترهای در نظر گرفته شده در زمان تعریف تابع باشد، از آرگومانهای اضافی صرف نظر میشود. مثلاً اگر تابع فوق را با ۶ آرگومان ورودی فراخوانی کنیم. فقط ۵ ورودی اول در نظر گرفته میشوند و ورودی ششم در نظر گرفته نمیشود.
mean(2 , 4 , 10 , 11 , 4 , 21);
← Average is : 6.2
اما اگر تعداد آرگومانهای ارسال شده به یک تابع در زمان فراخوانی کمتر از تعداد پارامترهای آن تابع باشد. در این صورت مقدار پارامترهایی که هیچ آرگومان ورودی برای آنها ارسال نشده است در بدنهی تابع برابر با undefined خواهد بود. به عنوان مثال اگر تابع mean را به صورت زیر و با ۴ آرگومان فراخوانی کنیم، با توجه به این که مقدار پارامتر e در داخل تابع برابر با undefined است. مجموع کل اعداد و میانگین آنها برابر با NaN خواهد بود.
mean(2 , 4 , 10 , 11);
← Average is : NaN
مثال فوق را میتوانید اینجا به صورت آنلاین اجرا کنید. سعی کنید مقدار و تعداد ورودیها را تغییر دهید و نتیجه را در حالتهای مختلف مشاهده کنید.
خروجی توابع
تمام توابعی که تا اینجا ایجاد کردیم، نتیجه را در کنسول نمایش میدادند. اما بیشتر توابعی که در عمل به کار برده میشوند در اکثر مواقع به این صورت عمل نمیکنند. در اکثر مواقع بهتر است که توابع نتیجهی محاسبات و پردازشهایی که بر روی ورودیهای خود انجام میدهند را به همان نقطهای که فراخوانی شدهاند بازگردانند. در این صورت برنامهنویس میتواند مقدار بازگشتی از تابع را در مکان و زمان مناسب به کاربر نمایش دهد. همچنین مزیت دیگر این روش این است که نتیجهی اجرای یک تابع را میتوان به عنوان ورودی به تابعی دیگر ارسال کرد تا پردازشهای دیگری بر روی آن انجام شود.
برای بازگرداندن نتیجه (یا خروجی) از یک تابع میتوان از کلمهی کلیدی return استفاده کرد. هر مقداری که در مقابل این کلمهی کلیدی قرار گیرد به عنوان خروجی تابع به محل فراخوانی تابع بازگردانده میشود. به عنوان مثال میتوان تابع mean را به صورت زیر اصلاح کرد.
function mean(a , b , c , d , e){
let average , total;
total = a + b + c + d + e;
average = total / 5;
return average;
}
در تابع فوق، پس از محاسبهی مقدار میانگین و ذخیرهسازی آن در متغیر average، مقدار این متغیر به عنوان خروجی به محل فراخوانی این تابع بازگردانده میشود. مثلاً فرض کنید تابع mean را به صورت زیر فراخوانی کنیم.
let avg;
avg = mean(2 , 4 , 10 , 11 , 4);
console.log("The function returned : " + avg);
← "The function returned : 6.2"
همانطور که مشاهده میکنید مقدار بازگشتی از تابع mean، دقیقاً در محل فراخوانی تابع جایگزین میشود. بنابراین مقدار بازگشتی در متغیر avg ذخیره میشود و پس از آن برنامهنویس میتواند این مقدار را به هر شکل دلخواهی و در هر محلی از برنامه به کار ببرد. که در مثال فوق این مقدار در کنسول نمایش داده شده است. این مثال را نیز میتوانید اینجا اجرا کنید.
نکته : در صورتی که هیچ مقداری با کلمهی کلید return از یک تابع بازگردانده نشود، مقدار undefined به صورت خودکار توسط تابع بازگردانده خواهد شد.
نکته : اجرای دستور return موجب پایان اجرای یک تابع و خروج از آن تابع میشود. بنابراین دستوراتی که بعد از دستور return در تابع قرار گرفته باشند اجرا نخواهند شد. همچنین میتوان در یک تابع از چندین دستور return در نقاط مختلف تابع استفاده کرد. اما با اجرای اولین دستور return اجرای تابع خاتمه خواهد یافت.
در بخش بعدی جزئیات بیشتر را در رابطه با ورودیهای توابع مورد بررسی قرار خواهیم داد.