۸- فانکشن

فانکشن – Functions

قطعه‌ای از کد است که برای انجام کاری در یک واحد بسته‌بندی شده. و اگر بر آن نامی نهاده شود، می‌توان هر جا که نیاز بود، آن را فراخواند و از آن استفاده کرد.

به کارگیری فانکشن، در هر زبانی دو مرحله دارد:
۱- تعریف – Define
۲- فراخوانی – Call

تعریف فانکشن

در جاواسکریپت، فانکشن به دو روش ساخته می‌شود:

Statement

در این روش یک فانکشن، با‌نام ویژه‌ای ساخته یا تعریف می‌شود. سپس با همان نام فراخوانی می‌شود.


// Define
function showMessage() {
    msg = 'Hello world!';
    alert(msg);
}

// Call
showMessage();        // Hello world!

Expression

در این روش یک فانکشن، بی‌نام ساخته، هم‌زمان در یک متغیر یا ثابت گذاشته می‌شود. سپس با نام آن متغیر یا ثابت فراخوانی می‌شود.


// Define
const showMessage = function() {
    msg = 'Hello world!';
    alert(msg);
};

// Call 
showMessage();        // Hello world!

داد و ستد اطلاعات

الف – ورود اطلاعات:

فانکشن برای دریافت اطلاعات از پارامتر و آرگومان استفاده می‌کند.

  • پارامتر – Parameter: متغیرهایی هستند که همراه با تعریف فانکشن، تعریف می‌شوند و از طریق آن اطلاعات به فانکشن داده می‌شود. (هنگام تعریف)
  • آرگومان – Argument: مقادیری هستند که هنگام فراخوانی فانکشن، درون پارامترها گذاشته می‌شوند. و پردازش روی آنها انجام می‌گیرد. (هنگام فراخوانی)

هنگام فراخوانی فانکشن، باید به ازای هر پارامتر، یک مقدار به فانکشن داده شود که به آن مقدار آرگومان می‌گویند.

Statement

// Define
function showMessage(name) {    // Parameter: name
    msg = 'Hello ' + name;
    alert(msg);
}

// Call
showMessage('bulbul');          // Argument: 'Hello bulbul'

Expression

// Define
const showMessage = function(name) {  // Parameter: name
    msg = 'Hello ' + name;
    alert(msg);
};

// Call 
showMessage('bulbul');                // Argument: 'Hello bulbul'

هنگام تعریف پارامتر می‌توانید مقداری را به عنوان پیش فرض تعیین کنید، تا اگر هنگام فراخوانی فانکشن، مقدار آرگومان داده نشد، از آن استفاده گردد.

Statement

// Define
function showMessage(name = 'world!') {
    msg = 'Hello ' + name;
    alert(msg);
}

// Call
showMessage();                // Hello World!
showMessage('bulbul');        // Hello bulbul

Expression

// Define
const showMessage = function(name = 'world!') {
    msg = 'Hello ' + name;
    alert(msg);
};

// Call
showMessage();                // Hello World!
showMessage('bulbul');        // Hello bulbul

ب – خروج اطلاعات

فانکشن می‌تواند با دستور return یک مقدار را برگرداند.

Statement

// Define
function sum(a, b) {
    return a + b;
}

// Call
let a = sum(2, 3);

alert(a);    // 5

Expression

// Define
const sum = function(a, b) {
    return a + b;
};

// Call
let a = sum(2, 3);

alert(a);    // 5

در دستور return از آپریتور ترنری نیز می‌توانید استفاده کنید.

Statement

// Define
function min(a, b) {
    return a < b ? a : b;
}

// Call
let a = min(2, 3);

alert(a);    // 2

Expression

// Define
const min = function(a, b) {
    return a < b ? a : b;
};

// Call
let a = min(2, 3);

alert(a);    // 2


تفاوت‌ها

الف – فراخوانی پیش از تعریف – Hoisting

یکی از تفاوت‌های این دو روش تعریف فانکشن، فراخوانی پیش از تعریف یا Hoisting است. در جاواسکریپت پیشاپیش همه فایل خوانده می‌شود و سپس خط به خط اجرا می‌گردد. بنابراین می‌توانید از فانکشنی که پایین‌تر تعریف شده استفاده کنید. به این ویژگی Hoisting یعنی بالا بردن می‌گویند. اما این ویژگی در فانکشن اکسپرشن کار نمی‌کند.

Statement

// Call
let a = sum(2, 3);    // a = 5



// Define
function sum(a, b) {
    return a + b;
}

Expression

// Call
let a = sum(2, 3);    // Error



// Define
const sum = function(a, b) {
    return a + b;
};

ب – اسکوپ

یکی دیگر از تفاوت‌های این دو روش تعریف فانکشن، اسکوپ است. تنها در روش اکسپرشن می توانید فانکشن را در یک بلوک تعریف کنید ولی بیرون آن فراخوانی کنید.

Statement

// conditionally declare a function
if (time < 12) {

    function welcome() { alert("Good morning"); }

} else {

    function welcome() { alert("Good afternoon"); }

}

// ...use it later
welcome(); // Error: welcome is not defined

Expression

let welcome;

// conditionally declare a function
if (time < 12) {

    welcome = function() { alert("Good morning"); };

} else {

    welcome = function() { alert("Good afternoon"); };

}

// ...use it later
welcome(); // Good morning

مثال بالا را با آپریتور ترنری نیز می‌توانید بنویسید.

Expression

let time = 10;

// Define
const welcome = (time < 12) ?
    function() { alert('Good morning'); } :
    function() { alert("Good afternoon"); };

// Call 
welcome();        // Good morning


توصیه‌ها

کارهایی که نرم افزار انجام می‌دهد را به اجزاء کوچک تقسیم کنید، سپس برای هر کدام یک فانکشن جداگانه بسازید.

هر فانکشن، تنها یک کار

هیچیک از فانکشن‌ها بیش از یک کار را انجام ندهد.

فانکشن، جایگزین کامنت

فانکشن برای اینست که فهم برنامه را آسان کند. به جای اینکه قدم به قدم با گذاشتن کامنت روند برنامه را برای خواننده روشن کنید، از فانکشن استفاده کنید.

فانکشن برای دیباگ

بخش بندی نرم افزار به بخش‌های کوچک و تبدیل هرکدام به یک فانکشن، دیباگ (پیدا کردن ارور) را آسان ‌می‌کند.

نامگذاری فانکشن

کاری که فانکشن انجام می‌دهد را در قالب یک فعل در نام آن بگنجانید.

  • getAge( ) – return the age.
  • calcSum( ) – calculate a sum.
  • createForm( ) – creates a form.
  • showMessage( ) – show a message.
  • isLogin( ) – checks the user is logged in.
  • hasRole( ) – checks the user permission.

مثال

HTML

<input type="text" id="in-box">
<button id="btn">OK</button>        
<h1 id="out-box"></h1>    

JS

const inBox = document.getElementById("in-box");
const outBox = document.getElementById("out-box");
const btn = document.getElementById("btn");

const isEven = function(n) {
    return (n % 2) ? false : true;
};

btn.onclick = function() {
    let n = inBox.value;
    outBox.innerHTML = isEven(n);
};

تمرین ۱

  • این فایل را دانلود کنید.
  • آن را در فولدر js1 باز کنید.
  • تنها فایل script.js را می‌توانید تغییر دهید.
  • هرگاه روی دکمه کلیک شد، از خانه بالا شعاع دایره خوانده شود و محیط دایره را در خانه پایین بنویسد. (برای محاسبه محیط یک فانکشن بنویسید.)


اَرو فانکشن – Arrow Function

اَرو فانکشن کوتاه شده فانکشن اکسپرشن است.

بجای کلمه function از علامت <= استفاده می‌شود.

Expression

// Define
const sum = function(a, b) {
    let c = a + b;
    return c;
};

// Call 
let n = sum(2, 3);        // n = 5

Arrow

// Define
const sum = (a, b) => {
    let c = a + b;
    return c;
};

// Call 
let n = sum(2, 3);        // n = 5

اگر بدنه فانکشن تنها یک خط داشته باشد، به کرلی برکت {} نیازی نیست.

Expression

// Define
const showMessage = function() { alert('Hello, World!'); };

// Call 
showMessage();        // Hello, World!

Arrow

// Define
const showMessage = () => alert('Hello, World!');

// Call 
showMessage();        // Hello, World!

اگر بدنه فانکشن تنها یک خط داشته باشد، به return نیازی نیست.

Expression

// Define
const sum = function(a, b) { return a + b; };

// Call 
let n = sum(2, 3);        // n = 5

Arrow

// Define
const sum = (a, b) => a + b;

// Call 
let n = sum(2, 3);        // n = 5

اگر فانکشن تنها یک پارامتر داشته باشد، به پرانتز نیازی نیست.

Expression

// Define
const half = function(a) { return a / 2 };

// Call 
let n = half(10);        // n = 5

Arrow

// Define
const half = a => a / 2;

// Call 
let n = half(10);        // n = 5

تمرین ۲

  • این فایل را دانلود کنید.
  • آن را در فولدر js1 باز کنید.
  • تنها فایل script.js را می‌توانید تغییر دهید.
  • همان تمرین یک را این بار با اَرو فانکشن بنویسید.


Immediately Invoked Function Expressions (IIFE)

در این روش یک فانکشن، تعریف و همزمان اجرا می‌شود. این روش با اینکه همان کارها را بیرون فانکشن انجام بدهید، هیچ تفاوتی نمی‌کند. غیر از اینکه عملیات درون یک اسکوپ قرار می‌گیرد و ایزوله می‌شود. بنابراین مقدار متغیرها و ثابت‌ها و … با بقیه برنامه تداخل ایجاد نمی‌کند. و احتمال خطا را پایین می‌آورد.


// Define & Call immediately

( function(msg) { alert(msg); } ('Hello, World!') );

// Or

( function(msg) { alert(msg); } ) ('Hello, World!');


ایونت‌های زمان

برای اینکه زمان اجرای کد را در جاواسکریپت، مدیریت کنید، دو ایونت برای آبجکت window وجود دارد. و چون آبجکت window، آبجکت گلوبال است، ننوشتن آن مشکلی ایجاد نمی کند.

setTimeout(function, delay, arg1, …)

یک فانکشن را پس از زمان خاصی به میلی ثانیه، اجرا می‌کند.
در مثال‌های زیر فانکشن، پس از ۱۰۰۰ میلی ثانیه اجرا می شوند.


// Functions without arguments
setTimeout(welcome, 1000);

// Functions with arguments
setTimeout(alret, 1000, 'Hello');

// Anonymous Functions without arguments
setTimeout(function() { ... }, 1000);

// Anonymous Functions with arguments
setTimeout(function(2, 5) { ... }, 1000);

setInterval(function, delay, arg1, …)

یک فانکشن را در پریود زمان خاصی پیوسته تکرار می‌کند.
در مثال‌های زیر فانکشن، هر ۱۰۰۰ میلی ثانیه یکبار اجرا می شوند.


// Functions without arguments
setInterval(welcome, 1000);

// Functions with arguments
setInterval(alret, 1000, 'Hello');

// Anonymous Functions without arguments
setInterval(function() { ... }, 1000);

// Anonymous Functions with arguments
setInterval(function(2, 5) { ... }, 1000);

clearTimeout(Timeout)

تایمر را متوقف می‌کند. و فانکشن اجرا نمی‌شود


// Set Timeout
const myFunc = setTimeout(...);

// Stop Timeout
clearTimeout(myFunc);

clearInterval(Interval)

تایمر را متوقف می‌کند. و فانکشن اجرا نمی‌شود


// Set Interval
const myFunc = setInterval(...);

// Stop Interval
clearInterval(myFunc);

تمرین ۳

  • این فایل را دانلود کنید.
  • آن را در فولدر js1 باز کنید.
  • تنها فایل script.js را می‌توانید تغییر دهید.
  • یک اَرو فانکشن بنویسید که یک عدد صحیح رندوم بین ۱ تا ۶ بدهد.
  • یک فانکشن بنویسید که با عدد رندوم تصویر را تغییر دهد.
  • این کار پیوسته در پریود زمانی کمی تکرار شود. یعنی تصویر، به صورت رندم تغییر کند.
  • هر گاه روی آن کلیک کردید متوقف شود.