توابع در زبان برنامه نویسی TypeScript
یک تابع بلوکی از کدهاست که به منظور انجام یک کار خاص ایجاد شده است. استفاده از توابع در برنامه نویسی باعث افزایش خوانایی برنامه و همچنین امکان استفاده مجدد از کدها می شود. توابع برنامه را به بلوک های منطقی تقسیم می کند. بعد از تعریف یک تابع، برای دسترسی به کدهای داخل آن باید از نام آن استفاده کنید. کامپایلر با استفاده از تعریف تابع، اطلاعاتی مانند نام تابع، نوع بازگشتی و پارامترهای آن را بدست می آورد.
ردیف | توضیحات |
1 | تعریف یک تابع تعریف یک تابع مشخص می کند که برای انجام چه کاری تعریف شده است و آن کار را چگونه انجام می دهد. |
2 | فراخوانی تابع برای اینکه کدهای داخل بلوک یک تابع اجرا شوند، باید آن را با استفاده از نام تابع فراخوانی کنیم. |
3 | مقدار بازگشتی از توابع توابع ممکن است بعد از انجام عملیات مشخص شده، یک مقدار را به عنوان نتیجه کار به کنترلی که آن را فراخوانی کرده، بازگردانند. |
4 | تابع پارامتریک پارامترها در حقیقت راهی برای ارسال مقادیر به توابع هستند. |
پارامترهای اختیاری
پارامترهای اختیاری همانطور که از اسم آن ها نیز مشخص است، زمانی استفاده می شوند که مشخص شدن یک پارامتر برای انجام عملیات یک تابع اجباری و ضروری نیست. به منظور تعریف پارامتر اختیاری می توانید یک علامت سوال (?) به انتهای نام پارامتر اضافه کنید. توجه داشته باشید که پارامترهای اختیاری همیشه باید به عنوان آخرین پارامترها باشند. در زیر سینتکس مربوط به تعریف تابع پارامتریک را مشاهده می کنید:
1 | function function_name (param1[:type], param2[:type], param3[:type]) |
مثال:
1 2 3 4 5 6 7 8 | function disp_details(id:number,name:string,mail_id?:string) { console.log("ID:", id); console.log("Name",name); if(mail_id!=undefined) console.log("Email Id",mail_id); } disp_details(123,"John"); disp_details(111,"mary","mary@xyz.com"); |
- در مثال بالا یک تابع با سه پارامتر تعریف شده است که پارامتر mail_id اختیاری است.
- اگر پارامتر mail_id در زمان فراخوانی تابع به تابع ارسال نشود، مقدار آن بر روی undefined تنظیم می شود.
- تابع فوق اگر مقدار mail_id برابر با undefined نباشد، مقدار آن را چاپ خواهد کرد.
خروجی کد فوق بعد از کامپایل:
1 2 3 4 5 6 7 8 9 | //Generated by typescript 1.8.10 function disp_details(id, name, mail_id) { console.log("ID:", id); console.log("Name", name); if (mail_id != undefined) console.log("Email Id", mail_id); } disp_details(123, "John"); disp_details(111, "mary", "mary@xyz.com"); |
خروجی برنامه:
1 2 3 4 5 | ID:123 Name John ID: 111 Name mary Email Id mary@xyz.com |
پارامترهای Rest
پارامترهای Rest شبیه به variable arguments در زبان برنامه نویسی Java است. این نوع پارامتر، محدودیتی برای تعداد پارامترها ندارد ولی باید نوع (type) همه آن ها یکی باشد (مثلا همگی از نوع رشته باشند.). برای اعلان یک پارامتر به صورت Rest باید قبل از نام آن سه عدد نقطه (…) قرار دهید. پارامترهای غیر Rest باید قبل از آن تعریف شوند.
مثال:
1 2 3 4 5 6 7 8 9 10 | function addNumbers(...nums: number[]) { var i; var sum: number = 0; for (i = 0; i < nums.length; i++) { sum = sum + nums[i]; } console.log("sum of the numbers", sum); } addNumbers(1, 2, 3); addNumbers(10, 10, 10, 10, 10); |
تابع فوق دوبار فراخوانی شده است که بار اول سه مقدار و بار دوم شش مقدار به آن داده شده است. همچنین تابع فوق با استفاده از حلقه for مقادیر ارسال شده را جمع کرده و نتیجه را چاپ می کند. خروجی کد فوق بعد از کامپایل:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function addNumbers() { var nums = []; for (var _i = 0; _i < arguments.length; _i++) { nums[_i - 0] = arguments[_i]; } var i; var sum = 0; for (i = 0; i < nums.length; i++) { sum = sum + nums[i]; } console.log("sum of the numbers", sum); } addNumbers(1, 2, 3); addNumbers(10, 10, 10, 10, 10); |
خروجی برنامه:
1 2 | sum of numbers 6 sum of numbers 50 |
پارامترهای پیشفرض (Default Parameters)
تابع می توانند پارامترهایی با مقدار پیشفرض داشته باشند. منظور از مقدار پیشفرض این است که اگر هنگام فراخوانی تابع مقداری برای آن پارامتر ارسال نشود، مقدار پیشفرض برای آن پارامتر تنظیم می شود. در زیر می توانید سینتکس مربوط به پارامتر پیش فرض را مشاهده کنید:
1 2 | function function_name(param1[:type],param2[:type] = default_value) { } |
مثال:
1 2 3 4 5 6 | function calculate_discount(price: number, rate: number = 0.5) { var discount = price * rate; console.log("Discount Amount: ", discount); } calculate_discount(1000); calculate_discount(1000, 0.3); |
خروجی کد فوق بعد از کامپایل:
1 2 3 4 5 6 7 8 9 10 | //Generated by typescript 1.8.10 function calculate_discount(price, rate) { if (rate === void 0) { rate = 0.5; } var discount = price * rate; console.log("Discount Amount: ", discount); } calculate_discount(1000); calculate_discount(1000, 0.3); |
خروجی برنامه:
1 2 | Discount amount : 500 Discount amount : 300 |
- در مثال فوق تابع calculate_discount دو پارامتر به نام های price و rate دارد.
- مقدار پارامتر rate به صورت پیشفرض بر روی 50 تنظیم شده است.
- تابع فوق دو بار فراخوانی شده است که بار اول فقط یک پارامتر به آن ارسال شده است و مقدار پارامتر دوم بر اساس مقدار پیشفرض مشخص شده است.
- بار دوم فراخوانی تابع هر دو پارامتر مقدار دهی شده اند. در این حالت مقدار پیشفرض نادیده گرفته می شود.
توابع Anonymous
توابعی که محدود به یک نام شناسه نیستند توابع Anonymous نامیده می شوند. این توابع به صورت پویا در runtime تعریف می شوند. مانند توابع عادی این نوع توابع نیز می توانند ورودی گرفته و خروجی را بازگردانند. معمولا یک تابع Anonymous بعد از ایجاد شدن اولیه دیگر در سایر بخش ها قابل دسترسی نیست. یک تابع Anonymous می تواند به عنوان مقدار یک متغیر تنظیم شود. به این نوع عبارت، عبارت تابع (Function Expression) گفته می شود. سینتکس مربوط به این نوع عبارت:
1 | var res = function( [arguments] ) { ... } |
مثال:
1 2 3 4 | var msg = function () { return "hello world"; }; console.log(msg()); |
کد فوق بعد از کامپایل شدن همان خروجی بالا را تولید می کند.
خروجی برنامه:
1 | hello world |
مثال تابع Anonymous با پارامتر:
1 2 3 4 | var res = function (a: number, b: number) { return a * b; }; console.log(res(12, 2)); |
کد فوق بعد از کامپایل:
1 2 3 4 5 | //Generated by typescript 1.8.10 var res = function (a, b) { return a * b; }; console.log(res(12, 2)); |
خروجی برنامه:
1 | 24 |
تفاوت عبارت تابع و اعلان تابع
عبارت تابع و اعلان تابع با هم متفاوت است. برخلاف اعلان تابع، عبارت تابع محدود به یک نام شناسه نیست. تفاوت اصلی بین این دو این است که اعلان تابع قبل از اینکه کدها اجرا شوند، پردازش می شوند ولی عبارت تابع هنگامی که کنترل اجرای برنامه با آن برخورد می کند، آن را پردازش می کند.
سازنده تابع (Function Constructor)
در زبان TypeScript شما می توانید با استفاده از Function() یک سازنده تابع ایجاد کنید. در زیر می توانید سینتکس مربوط به سازنده تابع را مشاهده کنید:
1 | var res = new Function( [arguments] ) { ... }. |
مثال:
1 2 3 | var myFunction = new Function("a", "b", "return a * b"); var x = myFunction(4, 3); console.log(x); |
عبارت new Function() یک رفرنس به تابع را ایجاد و آن را باز میگرداند. زمانی که کد فوق کامپایل شود، همان کد فوق را تولید می کند. خروجی برنامه:
1 | 12 |
توابع بازگشتی (Recursion)
Recursion یک تکنیک برای تکرار یک عمل با فراخوانی خود تابع است. به این صورت که تا زمانی که به نتیجه مورد نظر نرسیده ایم تابع خود را فراخوانی می کند. توابع بازگشتی زمانی مناسب است که می خواهید یک تابع را به صورت تکراری با ورودی های متفاوت فراخوانی کنید.
مثال:
1 2 3 4 5 6 7 8 9 | function factorial(number) { if (number <= 0) { // termination case return 1; } else { return number * factorial(number - 1); // function invokes itself } } console.log(factorial(6)); // outputs 720 |
کد کامپایل شده معادل کد فوق است. خروجی برنامه:
1 | 720 |
تابع بازگشتی Anonymous
در مثال زیر می توانید یک تابع بازگشتی Anonymous را مشاهده کنید:
1 2 3 4 | (function () { var x = "Hello!!"; console.log(x); })(); // the function invokes itself using a pair of parentheses () |
کد کامپایل شده معادل کد فق است. خروجی برنامه:
1 | Hello!! |
توابع Lambda
در برنامه نویسی Lambda به توابع Anonymous اشاره می کند. لامبدا مکانیسمی برای نمایش توابع Anonymous به صورت مختصر است. توابع لامبدا با نام Arrow functions هم شناخته می شوند.
آناتومی توابع لامبدا
یک تابع لامبدا از سه بخش تشکیل می شود:
- پارامترها (Parameters)
- علامت فلش =>
- دستورات
عبارت لامبدا (Lambda Expression)
عبارت لامبدا، اعلان یک تابع anonymous است که به خطی از کد اشاره دارد. در زیر سینتکس مربوط به یک عبارت لامبدا را مشاهده می کنید:
1 | ( [param1, parma2,…param n] )=>statement; |
مثال:
1 2 | var foo = (x: number) => 10 + x; console.log(foo(100)); //outputs 110 |
در مثال فوق یک تابع لامبدا تعریف شده است که نتیجه جمع عدد 10 با مقدار پارمتر x را باز میگرداند. کد فوق بعد از کامپایل شدن:
1 2 3 4 5 | //Generated by typescript 1.8.10 var foo = function (x) { return 10 + x; }; console.log(foo(100)); //outputs 110 |
خروجی برنامه:
1 | 110 |
دستورات لامبدا (Lambda Statement)
دستورات لامبدا، اعلان یک تابع anonymous است که به بلوکی از کد اشاره دارد. این سینتکس زمانی استفاده می شود که کد های مربوط به تابع بیش از یک خط داشته باشند.
1 2 3 | ([param1, parma2,…param n]) => { //code block } |
مثال:
1 2 3 4 5 | var foo = (x: number) => { x = 10 + x; console.log(x); }; foo(100); |
کد فوق بعد از کامپایل:
1 2 3 4 5 6 | //Generated by typescript 1.8.10 var foo = function (x) { x = 10 + x; console.log(x); }; foo(100); |
خروجی برنامه:
1 | 110 |
تغییرات سینتکسی
مشخص کردن نوع داده برای پارامتر ها اجباری نیست. و اگر نوع داده برای پارامتری مشخص نشود، از نوع any در نظر گرفته می شود. به تکه کد زیر توجه کنید:
1 2 3 4 5 6 7 8 9 | var func = (x) => { if (typeof x == "number") { console.log(x + " is numeric"); } else if (typeof x == "string") { console.log(x + " is a string"); } }; func(12); func("Tom"); |
کد فوق بعد از کامپایل:
1 2 3 4 5 6 7 8 9 10 | //Generated by typescript 1.8.10 var func = function (x) { if (typeof x == "number") { console.log(x + " is numeric"); } else if (typeof x == "string") { console.log(x + " is a string"); } }; func(12); func("Tom"); |
خروجی برنامه:
1 2 | 12 is numeric Tom is a string |
پارانتزهای اختیاری برای تک پارامتر
اگر عبارت لامبدا شما فقط یک پارامتر داشته باشد، میتواند پارانتزهای آن را حذف کنید. مثال:
1 2 3 4 | var display = (x) => { console.log("The function got " + x); }; display(12); |
کد فوق بعد از کامپایل:
1 2 3 4 5 | //Generated by typescript 1.8.10 var display = function (x) { console.log("The function got " + x); }; display(12); |
خروجی برنامه:
1 | The function got 12 |
براکت های اختیاری
اگر دستورات تابع فقط یک خط باشد، می توانید براکت ها را حذف کنید. مثال:
1 2 | var disp =()=> console.log("Function invoked"); disp(); |
عبارت لامبدا بدون پارامتر
در صورتی که عبارت لامبدا هیچ پارامتری نداشته باشد، باید از پرانتز خالی () استفاده کنید. مثال:
1 2 3 4 | var disp = () => { console.log("Function invoked"); }; disp(); |
کد فوق بعد از کامپایل:
1 2 3 4 5 | //Generated by typescript 1.8.10 var disp = function () { console.log("Function invoked"); }; disp(); |
خروجی:
1 | Function invoked |
سر بارگذاری تابع (Function Overloading)
توابع قابلیت انجام عملیات متفاوت با توجه به ورودی را دارند. به عبارت دیگر، یک برنامه می تواند چند تابع با نام مشابه داشته باشد که هر کدام ورودی متفاوتی دارد. این مکانیسم، سربارگذرای تابع نامیده می شود. زبان برنامه نویسی TypeScript نیز از این قابلیت پشتیبانی می کند.
برای سربارگذرای تابع در زبان تایپ اسکریپت باید مراحل زیر را دنبال کنید:
مرحله 1: چند تابع با نام مشابه اما با امضای متفاوت اعلان کنید. امضای یک تابع شامل موارد زیر است:
نوع داده پارامترها
1 2 | function disp(string):void; function disp(number):void; |
تعداد پارامترها
1 2 | function disp(n1:number):void; function disp(x:number,y:number):void; |
ترتیب قرار گیری پارامترها
1 2 | function disp(n1:number,s1:string):void; function disp(s:string,n:number):void; |
مرحله 2: تعریف تابع باید بر اساس اعلان آن انجام شود. اگر در طی overload کردن تابع، نوع داده پارامترها متفاوت باشد، باید آن ها را به صورت any تعریف کنید.
مرحله 3: در آخر باید تابع را فراخوانی کنیم.
مثال:
1 2 3 4 5 6 7 8 | function disp(s1:string):void; function disp(n1:number,s1:string):void; function disp(x:any,y?:any):void { console.log(x); console.log(y); } disp("abc") disp(1,"xyz"); |
- دو خط اول نشان دهنده سربارگذاری ها تابع است. تابع disp دو overload دارد.
- اولی فقط یک پارامتر از نوع رشته می گیرد.
- دومی دو پارامتر یکی از نوع عدد و دیگری از نوع رشته می گیرد.
- خط سوم تابع را تعریف می کند. نوع داده پارامترها به صورت any تنظیم شده است. همچنین پارامتر دوم اختیاری است.
- Overload های تابع در دو خط آخر فراخوانی می شوند.
کد فوق بعد از کامپایل:
1 2 3 4 5 6 7 | //Generated by typescript 1.8.10 function disp(x, y) { console.log(x); console.log(y); } disp("abc"); disp(1, "xyz"); |
خروجی برنامه:
1 | abc 1 xyz |
هیچ نظری ثبت نشده است