توابع در جاوا اسکریپت میتوانند همه چیز باشند، اما اولین چیز و مهمترین چیز اینه که قراردادی هستند. در واقع وقتی ما یک تابع رو ایجاد میکنید یا به اصطلاح تعریف میکنیم، قراردادی رو بین کسی که تابع رو صدا میزنه و از اون تابع استفاده میکنه و کسی که تابع رو ایجاد میکنه برقرار میکنیم.
نحوه کار با تابع بین سازنده و مصرف کننده اون قراردادی هست.
قرارداد تعیین میکنه که تابع «پارامتر های X, Y و Z» رو دریافت کنه و پاسخ R رو برگردونه.
و نکته قابل توجه این هست که این قرارداد همواره تغییر میکنه.
با یک مثال خیلی ساده شروع کنیم، تعریف یک تابع.
این قرارداد خیلی ساده است، دریافت کردن یک نام از طریق پارامتر-متغیر name و بازگشت دادن یک پیام خوشآمدی گویی. یک متغیر برای نام تمام چیزی است که ما نیاز داریم تا به تابع بفرستیم که هم نام و هم نامخانوادگی رو به شکل مشترک و واحد به تابع بفرستم.
بعد از تقریبا مدت زیادی که ما از این تابع با استفاده میکنیم، متوجه میشیم که به دریافت نامخانوادگی به صورت جداگانه هم نیاز داریم تا پیام خوشآمدی گویی ما کاملتر بشه. چون در خیلی از کشور ها و فرهنگ ها نامخانوادگی قبلتر از نام کوچک هست به همین دلیل ما ابتدا نام رو از طریق `firstName`، نامخانوادگی رو با کمک lastName در تابع دریافت میکنیم و یه متغیر از نوع Boolean لازم داریم که به ما وضعیت ترتیب نام و نامخانوادگی رو مشخص میکنه که ما اون رو isLastNameFirst (آیا نام خانوادگی اول میاد؟) نامگذاری و مقدار پیشفرض اون رو false قرار میدیم.
بیاییم یکبار دیگه تابع رو بازنویسی کنیم :
خب در داخل تابع بالا ما شرطی گذاشتیم که اگر پارامتر دوم یعنی lastName به تابع ارسال نشد به روش قبلی عمل کنه و در غیر این صورت مشخص بشه که ترتیب نام و نامخانوادگی به چه شکل هست.
حالا نوبت این هست که تمام راه های استفاده از این تابع رو با هم بررسی کنیم.
کد ما کاملا مشخص و خوانا است، ما میتونیم حدس بزنیم که پارامتر اولی نام هست و دومی نامخانوادگی. اما بدون اینکه قرارداد و نحوه ایجاد تابع بی خبر باشیم حدس اینکه مقدار true برای چه کاری استفاده میشه کاملا سخت میشه.
مشکل خیلی بزرگ و دردسر سازی نیست، چرا که ما در بیشتر محیط های توسعه (IDE) و ویرایشگر های کد (Code Editors) میتونیم به وسیله autocompletion اون رو تشخیص بدیم.
بعد از مدت ها استفاده از تابع با خودمون فکر میکنیم که بهتر هست با ادبتر باشیم و افراد رو پیشوند های مودبانه (مثل : جناب آقای یا سرکار خانم و ...) استفاده کنیم و چرا که نه، نام میانی رو هم اضافه کنیم، خب خیلی از کشور ها هستند که از اون استفاده میکنند و البته خیلی ها هم استفاده نمی کنند، پس ما ناممیانی رو به صورت اختیاری تعریف میکنیم.
و حالا ترتیب پارامتر ها .... بهتر هست راجع بهش حرفی نزنیم.
به هر حال بریم برای اضافه کردن پارامتر های جدید به تابع، و این یعنی باید تابع رو به شکل زیر تعریف کنیم :
خب از اون جهت که ما با خروجی کاری نداریم، پس با ساختار داخلی تابع هم کاری نداریم و صرفا با پارامتر ها (Parameters) و ورودی ها سروکار داریم، بنابراین، از تغییر داخل تابع صرف نظر میکنیم.
برگردیم و یکبار دیگه به مثال هایی که از تابع قابل انجام هست، شبیه سازی کنیم :
کافی با دقت بیشتری نگاه کنیم، میبینیم برای فرستادن آرگومان (Argument) های تابع، باید همه شون رو دونه دونه بفرستیم، و فرستادن یکی از اون ها بدون فرستادن آرگومان قبلی امکان پذیر نیست و ترتیب ارسال به تابع رو باید رعایت کنیم. حالا، جوری آرگومان ها رو به تابع ارسال میکنیم که مشکلی برای آرگومان های قبل از خودش پیش نیاید.
اگه شما از تایپ اسکریپت (Typescript) استفاده کنید، کدی که مینویسیم زشت اما امن میشه. اگه هم از جاوا اسکریپت (JavaScript) استفاده کنید، کدتون همچنان زشت و غیر امن میشه. و این یعنی شانس اینکه ما آرگومان اشتباهی رو در ترتیب و مکان اشتباه بفرستیم افزایش میده و این برای هر پارامتر جدیدی که برای تابع تعریف کنیم تکرار میشه. خب راه حل چیه؟
همه این مشکل به راحتی حل میشه اگه ما یه آبجکت (object) رو به عنوان پارامتر تابع استفاده کنیم و از ویژگی object destructing در جاوا اسکریپت استفاده کنیم.
قبل از اینکه بخواهیم شروع کنم خیلی خلاصه به object destructing (ساختار شکنی) نگاهی بندازیم :
حالا وقت اینه که مثال خودمون رو تکرار کنیم.
تابعی که نام رو دریافت کنه و پیام خوشآمدی گویی رو برگردونه :
حالا وقت اینه که با نام و نامخانوادگی جوری کار کنیم که با فرهنگ همه کشور ها سازگار باشه :
و حالا طبق مراحل قبل ما مقادیر «نام میانی» و «پیشوند» هم اضافه میکنیم :
نظرتون چیه؟ بهتر نشد؟!
استفاده از روش ساختارشکنی در آبجکت ها یه روش منعطف به حساب میاد، البته بیش از حد منعطف. با مثال شاید بشه راحت تر متوجه شد.
دقیقا در توابع جدید ما برای استفاده از isLastNameFirst حتما باید lastName رو قبلش مقداردهی کنیم و isLastNameFirst بدون lastName هیچ معنایی ندارد. در واقع مشکل در نحوه عملکرد تابع وجود نداره بلکه در نحوه تعریف قرارداد تابع هست که باید تغییر پیدا کنه.
به عنوان مثال، اگر ما برای lastName و isLastNameFirst پیوندی ایجاد کردیم، باید این پیوند داخل قراردادی که برای تابع تعریف کردیم هم منعکس بشه. مثل این روش نمونه (یا هر روش دیگهای) :
البته باید قبلش ذکر کنم که این استفاده از این روش خیلی ویژه است.
در اصل، قابلیت rest parameters به ما این اجازه رو میده تا به بینهایت آرگومان به شکل آرایه دسترسی داشته باشیم. مثلا تابع sum(...numbersToSum) یا اگر ما بخواهیم تابعی داشته باشیم که تمامی اعدادی که به اون ارسال میشه رو جمع کنه و برگردونه باید از این ساختارشکنی در آرایه ها استفاده کنیم.
خیلی از برنامه نویس ها هم با این روش موافق نیستند و دلیلش رو این میدونند که اگه قرار باشه برای هر بار صدا زدن تابع، آبجکت ها هم ساخته بشه، در کارایی و عملکرد برنامه تاثیر منفی میگذاره.
نکته اول اینکه، برای بیشتر نرم افزار هایی که با جاوا اسکریپت توسعه داده شدهاند این استدلال نامربوطی به حساب میاد یا مگر در موارد بسیار خاص که یک تابع هزار یا میلیون بار فراخوانی بشه. که در اون صورت، تفاوت رو خیلی حس نمی کنید.
و نکته دوم اینکه، برای اطمینان بیشتر، بهتر هست که امتحانش کنیم و مشاهده کنیم که تفاوت چقدر زیاد هست (البته اگر وجود داشته باشه)
من برای این کار از ابزار PerfLink استفاده میکنم تا برای مقایسه روش پارامتر های ترتیبی و پارمتر های نامگذاری شده در یک حلقه از تکرار نتایج مشخص شود، این هم نتایج : (ops/s بخوانید عملیات در ثانیه)
اما برداشت من از این موضوع (لطفا اگر اشتباه میکنم، تصحیح کنید) :
هر چه عملکرد برنامه فشردهتر باشه، تفاوت خیلی کمی رو ایجاد میکنه که نشون دهنده این هست که تاثیر ساختن شئ در برنامه یک عدد ناچیز به شمار میاد.
اگر از این مقاله خوشتون اومد خوشحال میشم که خوشی تون رو با نوشتن دیدگاه یا در شبکه های اجتماعی مثل تلگرام یا توئیتر یا حتی ردیت با من در میان بگذارید و اگر هم براتون مفید بود میتونید با دوستان تون هم به اشتراک بگذارید و اگر نظری یا پیشنهادی داری حتما برای من بفرست که من همه رو پاسخ میدم.
خوش باشید!
«رایانامه» | «تلگرام» | «گیت هاب» | «کدپن»
برگرفته از مقاله : "Stop Using Function Parameters Now" و یه مقاله دیگهای که متاسفانه لینکش رو فراموش کردم!! :|