آموزش جاوا اسکریپت مبتدی : توابع - بلوکهای کد قابل استفاده مجدد
یکی دیگر از مفاهیم اساسی در کدنویسی، توابع هستند که به شما امکان میدهند قطعه کدی را که یک کار واحد انجام میدهد، درون یک بلوک تعریفشده ذخیره کنید و سپس هر زمان که به آن نیاز داشتید، آن کد را با استفاده از یک دستور کوتاه فراخوانی کنید - به جای اینکه مجبور باشید همان کد را چندین بار تایپ کنید. در این مقاله، مفاهیم اساسی پشت توابع مانند سینتکس اولیه، نحوه فراخوانی و تعریف آنها، دامنه و پارامترها را بررسی خواهیم کرد.
توابع رو از کجا پیدا کنم؟
در جاوااسکریپت، توابع را همه جا پیدا خواهید کرد. در واقع، ما تاکنون در طول دوره از توابع استفاده کردهایم؛ فقط زیاد در مورد آنها صحبت نکردهایم. با این حال، اکنون زمان آن رسیده است که به طور صریح در مورد توابع صحبت کنیم و نحو آنها را بررسی کنیم.
تقریباً هر زمان که از یک ساختار جاوااسکریپت که دارای یک جفت پرانتز است - () - استفاده میکنید و از یک ساختار رایج زبان داخلی مانند حلقه for، حلقه while یا یا دستور استفاده نمیکنید، در حال استفاده از یک تابع هستید.
ما در این دوره به طور گسترده از توابع داخلی مرورگر استفاده کردهایم.
هر بار که یک رشته متنی را دستکاری میکردیم، به عنوان مثال:
یا هر بار که یک آرایه را دستکاری میکردیم:
یا هر بار که یک عدد تصادفی تولید میکنیم:
ما از یک تابع استفاده میکردیم!
توجه: در صورت نیاز، میتوانید این خطوط را در کنسول جاوا اسکریپت مرورگر خود وارد کنید تا با عملکرد آنها آشنا شوید.
زبان جاوا اسکریپت توابع داخلی زیادی دارد که به شما امکان میدهد کارهای مفیدی انجام دهید بدون اینکه مجبور باشید خودتان همه آن کدها را بنویسید. در واقع، برخی از کدهایی که هنگام فراخوانی (یک کلمه فانتزی برای اجرا یا اجرا کردن) یک تابع داخلی مرورگر فراخوانی میکنید، نمیتوانند در جاوا اسکریپت نوشته شوند - بسیاری از این توابع بخشهایی از کد مرورگر پسزمینه را فراخوانی میکنند که عمدتاً به زبانهای سیستمی سطح پایین مانند نوشته شده است، نه زبانهای وب مانند جاوا اسکریپت.
به خاطر داشته باشید که برخی از توابع داخلی مرورگر بخشی از زبان اصلی جاوا اسکریپت نیستند - برخی به عنوان بخشی از APIهای مرورگر تعریف میشوند که بر روی زبان پیشفرض ساخته میشوند تا عملکردهای بیشتری را ارائه دهند (برای توضیحات بیشتر به این بخش اولیه دوره ما مراجعه کنید). ما در ماژول بعدی به استفاده از APIهای مرورگر با جزئیات بیشتر خواهیم پرداخت.
توابعی که بخشی از اشیاء هستند، متد نامیده میشوند؛ در ادامهی این ماژول در مورد اشیاء بیشتر خواهید آموخت. فعلاً، ما فقط میخواستیم هرگونه سردرگمی احتمالی در مورد متد در مقابل تابع را برطرف کنیم - احتمالاً با نگاه به منابع مرتبط در سراسر وب با هر دو اصطلاح مواجه خواهید شد.
کد داخلی که تاکنون استفاده کردهایم به دو شکل ارائه میشود: توابع و متدها. میتوانید لیست کامل توابع داخلی و همچنین اشیاء داخلی و متدهای مربوط به آنها را در مرجع جاوا اسکریپت ما بررسی کنید.
همچنین تاکنون توابع سفارشی زیادی را در این دوره دیدهاید - توابعی که در کد شما تعریف شدهاند، نه در داخل مرورگر. هر زمان که یک نام سفارشی را با پرانتز بلافاصله پس از آن دیدید، از یک تابع سفارشی استفاده میکردید. در مثال ما (همچنین به کد منبع کامل مراجعه کنید) از مقاله حلقههای ما، ما یک تابع سفارشی را گنجاندهایم که به این شکل بود:
این تابع ۱۰۰ دایره تصادفی درون یک عنصر رسم میکند. هر بار که بخواهیم این کار را انجام دهیم، میتوانیم تابع را با این دستور فراخوانی کنیم:
به جای اینکه مجبور باشیم هر بار که میخواهیم آن را تکرار کنیم، دوباره همه آن کد را بنویسیم. توابع میتوانند شامل هر کدی باشند که دوست دارید - حتی میتوانید توابع دیگر را از داخل توابع فراخوانی کنید. برای مثال، تابع که در بالا دیده میشود، تابع را سه بار فراخوانی میکند؛ با کد زیر تعریف میشود:
ما به این تابع نیاز داشتیم زیرا تابع داخلی مرورگر فقط یک عدد اعشاری تصادفی بین ۰ و ۱ تولید میکند. ما یک عدد صحیح تصادفی بین ۰ و یک عدد مشخص میخواستیم.
احتمالاً تا الان متوجه شدهاید، اما برای اطمینان، برای استفاده از یک تابع پس از تعریف آن، باید آن را اجرا یا فراخوانی کنید. این کار با قرار دادن نام تابع در جایی از کد و به دنبال آن قرار دادن پرانتز انجام میشود.
این شکل از ایجاد یک تابع، به عنوان تعریف تابع نیز شناخته میشود. همیشه تابع بالا نگه داشته میشود تا بتوانید تابع را بالای تعریف تابع فراخوانی کنید و به خوبی کار کند.
برخی از توابع هنگام فراخوانی نیاز به مشخص کردن پارامترهایی دارند - اینها مقادیری هستند که باید درون پرانتزهای تابع قرار گیرند، که برای انجام صحیح کار خود به آنها نیاز دارند.
پارامترها گاهی ورودی یا ویژگی نامیده میشوند.
به عنوان مثال، تابع داخلی مرورگر به هیچ پارامتری نیاز ندارد. هنگام فراخوانی، همیشه یک عدد تصادفی بین 0 و 1 برمیگرداند:
تفاوت اصلی parameter و argument این است که به ورودی فرضی تابع هنگام تعریف، پارامتر و به ارزش ورودی واقعی تابع هنگام اجرا آرگیومنت میگوییم.
با این حال، تابع داخلی رشته مرورگر به دو پارامتر نیاز دارد - زیررشتهای که باید در رشته اصلی پیدا شود و زیررشتهای که باید آن رشته را با آن جایگزین کند:
وقتی نیاز به مشخص کردن چندین پارامتر دارید، آنها را با کاما از هم جدا میکنید.
گاهی اوقات پارامترها اختیاری هستند - لازم نیست آنها را مشخص کنید. اگر این کار را نکنید، تابع معمولاً نوعی رفتار پیشفرض را اتخاذ میکند. به عنوان مثال، پارامتر تابع آرایه اختیاری است:
اگر هیچ پارامتری برای مشخص کردن کاراکتر اتصال/جداکننده وارد نشود، به طور پیشفرض از کاما استفاده میشود.
اگر در حال نوشتن یک تابع هستید و میخواهید از پارامترهای اختیاری پشتیبانی کنید، میتوانید با اضافه کردن علامت = بعد از نام پارامتر و به دنبال آن مقدار پیشفرض، مقادیر پیشفرض را مشخص کنید:
توابع بی نام و توابع پیکانی
تا اینجا، ما فقط توابعی مانند زیر ایجاد کردهایم:
اما شما همچنین میتوانید تابعی ایجاد کنید که نامی نداشته باشد:
این تابع، تابع ناشناس نامیده میشود، زیرا نامی ندارد. اغلب توابع ناشناس را زمانی میبینید که یک تابع انتظار دارد تابع دیگری را به عنوان پارامتر دریافت کند. در این حالت، پارامتر تابع اغلب به عنوان یک تابع ناشناس ارسال میشود.
این شکل از ایجاد یک تابع، به عنوان عبارت تابع نیز شناخته میشود. برخلاف تعریف تابع، عبارات تابع جابجا نمیشوند.
برای مثال، فرض کنید میخواهید وقتی کاربر در یک کادر متنی تایپ میکند، کدی اجرا شود. برای انجام این کار، میتوانید تابع مربوط به کادر متنی را فراخوانی کنید. این تابع از شما انتظار دارد که حداقل دو پارامتر به آن ارسال کنید:
نام رویدادی که باید به آن گوش دهید، که در این مورد keydown است.
تابعی که هنگام وقوع رویداد اجرا میشود.
وقتی کاربر کلیدی را فشار میدهد، مرورگر تابعی را که ارائه کردهاید فراخوانی میکند و پارامتری حاوی اطلاعات مربوط به این رویداد، از جمله کلید خاصی که کاربر فشار داده است، به آن ارسال میکند:
به جای تعریف یک تابع جداگانه، میتوانید یک تابع ناشناس را به ارسال کنید:
توابع پیکانی arrow functions
اگر یک تابع ناشناس مانند این ارسال کنید، میتوانید از یک شکل جایگزین به نام تابع پیکانی استفاده کنید. به جای بنویسید:
اگر تابع فقط یک پارامتر میگیرد، میتوانید پرانتزهای اطراف پارامتر را حذف کنید:
در نهایت، اگر تابع شما فقط شامل یک خط است که آن هم دستور return است، میتوانید آکولادها و کلمه کلیدی return را حذف کنید و به طور ضمنی عبارت را برگردانید. در مثال زیر، ما از متد از Array برای دو برابر کردن هر مقدار در آرایه اصلی استفاده میکنیم:
متد هر آیتم در آرایه را به تابع داده شده ارسال میکند، سپس مقدار برگردانده شده توسط تابع را گرفته و به یک آرایه جدید اضافه میکند.
تابع arrow بسیار مختصر است؛ بازنویسی کد ما برای استفاده از یک تابع فراخوانی ناشناس معمولی به این صورت خواهد بود:
میتوانید از همان سینتکس مختصر تابع arrow برای بازنویسی مثال استفاده کنید:
در این حالت، مقدار که تعریف نشده است، به طور ضمنی از تابع فراخوانی برگشت داده میشود.
ما استفاده از توابع arrow را توصیه میکنیم، زیرا میتوانند کد شما را کوتاهتر و خواناتر کنند. برای کسب اطلاعات بیشتر، به بخش توابع arrow در راهنمای جاوا اسکریپت و صفحه مرجع ما در مورد توابع arrow مراجعه کنید.
تفاوتهای ظریفی بین توابع arrow و توابع معمولی وجود دارد. آنها خارج از محدوده این آموزش مقدماتی هستند و بعید است که در مواردی که در اینجا مورد بحث قرار دادهایم، تفاوتی ایجاد کنند. برای کسب اطلاعات بیشتر، به مستندات مرجع تابع arrow مراجعه کنید.
در اینجا یک نسخه کامل و کاربردی از مثال keydown که در بالا مورد بحث قرار دادیم، آورده شده است:
HTML:
بیایید کمی در مورد دامنه صحبت کنیم - یک مفهوم مهم هنگام کار با توابع. وقتی یک تابع ایجاد میکنید، متغیرها و سایر چیزهایی که درون تابع تعریف میشوند، درون دامنه جداگانه خود قرار دارند. این بدان معناست که آنها در محفظه جداگانه خود قفل شدهاند و از کد خارج از توابع قابل دسترسی نیستند.
سطح بالای خارج از همه توابع شما، دامنه سراسری نامیده میشود. مقادیر تعریف شده در دامنه سراسری از همه جای کد قابل دسترسی هستند.
جاوااسکریپت عمدتاً برای امنیت و سازماندهی اینگونه کار میکند. گاهی اوقات نمیخواهید متغیرها از همه جای کد قابل دسترسی باشند. اسکریپتهای خارجی که از جاهای دیگر فراخوانی میشوند، میتوانند در صورت استفاده از نامهای متغیر یکسان، کد شما را خراب کنند و باعث ایجاد مشکل شوند و باعث تداخل شوند. این ممکن است از روی بدخواهی یا فقط به طور تصادفی انجام شود.
به عنوان مثال، فرض کنید یک فایل HTML دارید که به دو فایل جاوااسکریپت خارجی ارجاع میدهد و هر دوی آنها یک متغیر و یک تابع تعریف شده دارند که از نام یکسانی استفاده میکنند:
نگهبان باغ وحش مانند یک گلوبال اسکوپ است - آنها کلیدهای دسترسی به هر محوطه، ذخیره مجدد غذا، مراقبت از حیوانات بیمار و غیره را دارند.
هنگامی که مثال در مرورگر رندر میشود، ابتدا یک کادر هشدار با عبارت . مشاهده خواهید کرد، به این معنی که تابع که در فایل اسکریپت اول تعریف شده است، توسط فراخوانی در اسکریپت داخلی فراخوانی شده است.
با این حال، اسکریپت دوم به هیچ وجه بارگذاری و اجرا نمیشود و خطایی در کنسول چاپ میشود: قبلاً اعلام شده است. دلیل این امر این است که ثابت name قبلاً در اعلام شده است و شما نمیتوانید یک ثابت را دو بار در یک محدوده اعلام کنید. از آنجا که اسکریپت دوم بارگذاری نشده است، تابع از برای فراخوانی در دسترس نیست.
اگر خط را از حذف کنیم و صفحه را دوباره بارگذاری کنیم، هر دو اسکریپت اجرا میشوند. کادر هشدار اکنون میگوید: شرکت ما کریس نام دارد. اگر یک تابع دوباره تعریف شود، آخرین تعریف در ترتیب منبع استفاده میشود. تعریفهای قبلی عملاً بازنویسی میشوند.
قفل کردن بخشهایی از کد شما در توابع از چنین مشکلاتی جلوگیری میکند و بهترین روش محسوب میشود.
کمی شبیه باغ وحش است. شیرها، گورخرها، ببرها و پنگوئنها در محوطههای مخصوص به خود نگهداری میشوند و فقط به چیزهای داخل آن دسترسی دارند، مشابه محدودههای تابع. اگر آنها میتوانستند وارد محوطههای دیگر شوند، مشکلاتی رخ میداد. در بهترین حالت، حیوانات مختلف در زیستگاههای ناآشنا احساس ناراحتی زیادی میکردند - یک شیر یا ببر در قلمرو آبکی و یخی پنگوئنها احساس وحشتناکی خواهد داشت. در بدترین حالت، شیرها و ببرها ممکن است سعی کنند پنگوئنها را بخورند!

نگهبان باغ وحش مانند یک گلوبال اسکوپ است - آنها کلیدهای دسترسی به هر محوطه، ذخیره مجدد غذا، مراقبت از حیوانات بیمار و غیره را دارند.
نگاهی گذرا بر حلقه و دامنه شرطی
شایان ذکر است که دامنه مقادیر اعلام شده در داخل شرطها و حلقهها، همانند دامنه تابع هنگام اعلام مقادیر با let و const عمل میکند. به عنوان مثال، اگر بلوکهای زیر را به مثال بالا اضافه کنید:
فراخوانی یا منجر به همان خطای میشود که قبلاً دیده شد. تابع نمیتواند به این متغیرها دسترسی داشته باشد زیرا آنها در محدوده خود قفل شدهاند.
کلمه کلیدی var قدیمی متفاوت عمل میکند. اگر c، d، e و f با استفاده از var تعریف شده باشند:
آنها به محدوده سراسری منتقل میشوند؛ بنابراین، ارسال آنها به کنسول (برای مثال، با ) کار میکند. با این حال، متغیرهایی که با var درون توابع تعریف میشوند، همچنان محدوده خود را به همان توابع محدود میکنند.
این ناسازگاری میتواند باعث سردرگمی و خطا شود و دلیل دیگری است که چرا باید به جای var از let و const استفاده کنید.