توابع بلوک هایی از کدهای برنامه نویسی هستند که قابلیت استفاده مجدد در سراسر برنامه دارند. توابع توسط کلمه کلیدی function تعریف می شوند. نحوه تعریف یک تابع استاندارد به شکل زیر است:
function function_name() { // function body }
برای اجرای یک تابع، باید آن را فراخوانی کرد. به اینکار فراخوانی تابع می گویند. نحوه فراخوانی یک تابع مانند زیر است:
function_name()
//define a function function test() { console.log("function called") } //call the function test()
مثال بالا یک متد به نام test() را ایجاد می کند. کدهایی که بین علامت های {} قرار دارند، بدنه تابع و همچنین قلمرو تابع می گویند. یک تابع برای اجرا حتما باید فراخوانی شود.
خروجی کد بالا:
function called
توابع می توانند به نوع های برگشت دهنده و پارامتری تقسیم شوند.
توابعی که بعد از اجرای کدهای بدنه خود، یک مقداری را به برنامه فراخوان بر می گردانند را توابع برگشت دهنده می گویند.
نحوه تعریف این نوع توابع عبارت است از:
function function_name() { //statements return value; }
در انتهای این نوع از توابع باید از کلمه کلیدی return استفاده کرد.
یک تابع فقط می تواند یک مقدار را برگرداند.
عبارت return باید در انتهای تابه نوشته شود.
کدهای زیر نحوه استفاده از دستور return را نمایش می دهد.
function retStr() { return "hello world!!!" } var val = retStr() console.log(val)
در کد بالا، یک تابع تعریف کرده ایم که مقدار رشته ای hello world را بر می گرداند.
خروجی کدهای بالا
hello world!!!
پارامترها مکانیزمی برای ارسال مقادیر به تابع هستند. پارامترها بخشی از امضای تابع می باشند.
در طی اجرای یک تابع پارامترها به آن پاس داده می شوند. تعداد پارامترهایی که به یک تابع پاس داده می شوند باید با تعداد پارامترهای هنگام تعریف یک تابع برابر باشند.
کد زیر نحوه تعریف تابع پارامتری را نشان می دهد:
function func_name( param1,param2 ,…..paramN) { ...... ...... }
در مثال زیر یک تابع تعریف کردیم که دو پارامتر به نام های n1 و n2 را گرفته و آنها را با هم جمع و نتیجه را در خروجی نمایش می دهد، و در زمان اجرا تابع، مقادیر به آن پاس داده می شود.
function add( n1,n2) { var sum = n1 + n2 console.log("The sum of the values entered "+sum) } add(12,13)
خروجی
The sum of the values entered 25
در ES6 یک تابع اجازه می دهد که پارامترهایش مقدار اولیه بگیرند و در صورتی که در هنگام اجرا هیچ پارامتری به عنوان ارسال نشد، تابع از همان مقدار اولیه یا پیش فرض استفاده می کند.
کدهای زیر راببینید:
function add(a, b = 1) { return a+b; } console.log(add(4))
در تابع بالا، به پارامتر b مقدار پیش فرض 1 را داده ایم و در صورتی که در هنگام اجرای تابع به طور صریح مقداری برای پارامتر b ارسال نشود، تابع از همان مقدار پیش فرض یعنی 1 استفاده می کند.
خروجی
5
درصورتی که به طور صریح مقداری برای تابع ارسال شود، تابع به جای استفاده از مقدار پیش فرض از همان مقداری که پاس داده شده استفاده می کند.
function add(a, b = 1) { return a + b; } console.log(add(4,2))
در کد بالا، بطور صریح مقدار 2 را برای پارامتر b ارسال کردیم، بنابراین تابع از این مقدار به جای مقدار پیش فرض استفاده می کند.
خروجی عبارت است از:
6
پارامترهای Rest همانند آرگومان های متغیر در جاوا هستند. پارامترهای Rest تعداد مقادیری که یک تابع می تواند به آن ارسال کند را محدود نمی کند.
اگر چه تمام مقادیر ارسال شده باید از یک نوع باشند.به عبارت دیگر پارامترهای rest به عنوان یک placeholder برای چندین آرگومان از یک نوع مورد استفاده قرار می گیرد.
برای تعریف یگ پارامتر rest باید قبل از نام پارامتر سه تا نقطه قرار دهیم که به آن عملگر spread هم گفته می شود.
در کد زیر نحوه انجام اینکار را می بینید.
function fun1(...params) { console.log(params.length); } fun1(); fun1(5); fun1(5, 6, 7);
خروجی کد بالا:
0 1 3
تذکر مهم: دقت داشته باشید که پارامترهای rest باید در انتهای لیست پارامترهای یک تابع قرار بگیرند.
توابعی که هیچ شناسه ای به آن اختصاص داده نشده، توابع بی نام می گویند. این توابع به طور دینامیک در هنگام اجرا اعلان می شود.
این توابع همانند توابع استاندارد ورودی هایی را گرفته و مقادیری را در خروجی به ما بر می گردانند. هنگام تعریف یک تابع بی نام، معمولاً نمی توان مستقیم به آن دسترسی داشت، بلکه باید این توابع را به یک متغیر نسبت دهید.
نحوه تعریف یک تابع بی نام مانند زیر است:
var res = function( [arguments] ) { ... }
var f = function(){ return "hello"} console.log(f())
خروجی
hello
var func = function(x,y){ return x*y }; function product() { var result; result = func(10,20); console.log("The product : "+result) } product()
خروجی
he product : 200
دستور function تنها روش تعریف یک تابع نیست، بلکه شما می توانید توابع را با متد سازنده Function هم تعریف کنید. نحوه تعریف یک تابع را با استفاده از سازنده Function همراه با اپراتور جدید را در زیر می بینید:
var variablename = new Function(Arg1, Arg2..., "Function Body");
متد سازنده Function() تعدادی آرگومان رشته ای میگیرد. آرگومان آخر بدنه تابع را مشخص می کند که شامل کدهای جاوا اسکریپت است و هر دو دستور با یک دستور سمی کولن از هم جدا می شوند
سازنده Function هیچ آرگومانی را برای متدی که آنرا ایجاد کرده، ارسال نمی کند.
var func = new Function("x", "y", "return x*y;"); function product() { var result; result = func(10,20); console.log("The product : "+result) } product()
در مثال بالا، از سازنده Function برای تعریف یک تابع بی نام استفاده کردیم. این تابع دو پارامتر گرفته و یک product را به عنوان خروجی بر می گرداند.
خروجی
The product : 200
Recursion یا الگوریتم بازگشتی زمانی اتفاق می افتد که یک متد خود را به کرات صدا بزند. به متدی که خود را فراخوانی می کند، در اصطلاح تابع recursive یا بازگشتی می گویند.
function factorial(num) { if(num<=0) { return 1; } else { return (num * factorial(num-1) ) } } console.log(factorial(6))
در مثال بالا تابع خودش را فراخوانی کرده است. خروجی کد بالا:
720
(function() { var msg = "Hello World" console.log(msg) })()
در کد بالا می بینید که یک تابع خودش را توسط یک جفت پرانتز () فراخوانی کرده است.
خروجی بالا
Hello World
لامبدا ارجاعی به توابع بی نام در برنامه نویسی است. توابع لامبدا یک مکانیزم کوتاه برای نمایش توابع بی نام هستند.
به این توابع Arrow function هم گفته می شود
توابع لامبدا از سه بخش تشکیل شده است.
نکته: بطور قراردادی، از پارامتر تک حرفی برای اعلان دقیق و فشرده تابع استفاده می شود.
عبارت لامبدا یک روش تابع بی نام است که در یک خط انجام می گیرد
([param1, parma2,…param n] )=>statement;
مثال – عبارت لامبدا
var foo = (x)=>10+x console.log(foo(10))
مثال بالا روش تعریف یک متد لامبدا را نمایش می دهد. این تابع عدد 10 را با پارامتری که به این تابع پاس داده شده است، جمع می کند و نتیجه را بر می گرداند.
خروجی
20
نوعی تعریف توابع بی نام است که در آن بدنه تابع حاوی چندین خط کد بوده و همه آنها تشکیل یک بلوک می دهند.
( [param1, parma2,…param n] )=> { //code block }
مثال – دستورات لامبدا
var msg = ()=> { console.log("function invoked") } msg()
ارجاعی از تابع برگشت داده شده در متغیر msg ذخیده می شود.
خروجی کد بالا:
unction invoked
قرار دادن پرانتز برای تابعی که یک پارامتر دارد اختیاری است.
var msg = x=> { console.log(x) } msg(10)
علامت آکولاد { } برای توابعی که یک دستور دارند اختیاری است.
var disp = ()=>console.log("Hello World") disp();
نمایش تابع و اعلان تابع به یک معنی نیستند. بر خلاف نمایش یک تابع، اعلان یک تابع توسط نام تابع انجام می شود.
تفاوت اساسی بین این دو در این است که اعلان تابع قبل از اجرای آن تفسیر (پردازش) می شود، اما نمایش تابع موقعی پردازش می شود که موتور جاوا اسکریپت با آن در هنگام اجرا برخورد داشته باشد.
هنگامی که مفسر جاوا اسکریپت با یک تابع در کد اصلی برنامه برخورد کند، فرض می کند که یک اعلان تابع رخ داده است. اما هنگامی که یک تابع در بخشی از یک دستور ظاهر شود، به عنوان نمایش تابع تفسیر می شود.
Hoisting در واقع به یک رفتار پیش فرض زبان جاوا اسکریپت اطلاق می گردد. این رفتار عبارت است از انتقال خودکار تعریف متغیر (variable declaration) به بالای حوزه (scope) جاری.
در جاوا اسکریپت این امکان وجود دارد که یک متغیر را پیش از اینکه تعریف شود بکار برد. به عبارتی دیگر می توان متغیر را مورد استفاده قرار داده، بعدا آن را تعریف کرد.
همانند متغیرها، توابع هم می توانند hoist شوند. بر خلاف متغیرها، هنگامی که اعلان یک تابع hoist شود، تعریف تابع hoist می شود نه نام تابع.
کد زیر نحوه hoist کردن یک تابع در جاوا اسکرپیت را نشان می دهد.
hoist_function(); function hoist_function() { console.log("foo"); }
خروجی
foo
اگر چه عبارت یک تابع نمی تواند hoist شود.
hoist_function(); // TypeError: hoist_function() is not a function var hoist_function() = function() { console.log("bar"); };
فراخوانی فوری یک تابع (IIFEs) می تواند برای جلوگیری از hoist متغیر از داخل بلوک استفاده می شود. اینکار اجازه می دهد دسترسی عمومی به متدها داشته باشیم در حالی که متغیرهای داخل تابع را هم بصورت خصوصی نگه داریم.
این الگو توابع بی نام خود - اجرا هم نامیده می شود. کد زیر این مفهوم را بهتر توضیح می دهد.
مثال 1 - IIFE
var main = function() { var loop = function() { for(var x = 0;x<5;x++) { console.log(x); } }(); console.log("x can not be accessed outside the block scope x value is :"+x); } main();
مثال 2 - IIFE
var main = function() { (function() { for(var x = 0;x<5;x++) { console.log(x); } })(); console.log("x can not be accessed outside the block scope x value is :"+x); } main();
خروجی کدهای بالا:
0 1 2 3 4 Uncaught ReferenceError: x is not define
هنگامی که یک تابع معمولی فراخوانی شود، کنترل برنامه تا زمانی که تابع یک مقدار را برگرداند (return)، به تابع فراخوانی شده منتقل می شود.
با Generatorها در ES6، تابع فراخوان کنترل اجرای تابع فراخوانی شده را بر عهده می گیرد.
تابع Generator همانند تابع معمولی است با این تفاوت که:
مثال زیر را ببینید:
"use strict" function* rainbow() { // the asterisk marks this as a generator yield 'red'; yield 'orange'; yield 'yellow'; yield 'green'; yield 'blue'; yield 'indigo'; yield 'violet'; } for(let color of rainbow()) { console.log(color); }
Generatorها یک ارتباط دو طرفه بین فراخوان و تابع فراخوانی شده برقرار می کنند. اینکار توسط کلمه کلیدی yield انجام می شود.
مثال زیر را ببینید:
function* ask() { const name = yield "What is your name?"; const sport = yield "What is your favorite sport?"; return `${name}'s favorite sport is ${sport}`; } const it = ask(); console.log(it.next()); console.log(it.next('Ethan')); console.log(it.next('Cricket'));
روش کار یک تابع Generator مطابق زیر است:
خروجی کدهای بالا:
{ value: 'What is your name?', done: false } { value: 'What is your favorite sport?', done: false } { value: 'Ethan\'s favorite sport is Cricket', done: true }
نکته: توابع Generator نمی توانند توسط arrow function نمایش داده شوند.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.