مقدمه

در درس قبل با تعریف توابع به عنوان بلاک‌های کدِ دارای قابلیت استفاده‌ی مجدد آشنا شدیم. دیدیم که یک تابع را می‌توان با استفاده از نامش در هر جایی از برنامه فرخوانی و اجرا کرد. اما در جاوااسکریپت، یک تابع را می‌توان به عنوان یک مقدار هم در نظر گرفت. این یعنی اینکه در هر جایی از برنامه که انتظار یک مقدار می‌رود، می‌توانیم از یک تابع استفاده کنیم. مثلاً یک تابع را می‌توانیم به یک متغیر تخصیص دهیم یا به عنوان آرگومان به یک تابع دیگر پاس کنیم. در این درس به این موضوع کلیدی می‌پردازیم که جاوااسکریپت چطور با یک تابع مثل یک مقدار رفتار می‌کند و با سینتکس Function Expression برای تعریف توابع آشنا خواهیم شد.

تابع به عنوان مقدار

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

تابع به عنوان مقدار یک متغیر

یک گزاره‌ی تخصیص (assignment statement) در جاوااسکریپت دارای فرم کلی زیر است:

let variable = value;

در سمت راست یک گزاره‌ی تخصیص به یک مقدار نیاز است. این مقدار می‌تواند بک مقدار ساده مثل 5 یا "Hi" باشد یا یک عبارت (Expression) پیچیده‌تر که به یک مقدار ارزیابی می‌شود و یا یک تابع. به مثال زیر دقت کنید.

Copy Icon functions.js
function sayHello() {
  console.log("Hello, world!");
}

function add(a, b) {
  return a + b;
}

let summation = add(5, 3); // 8 
let greeting = sayHello(); // undefined 

let sum = add; // sum is now a reference to the add function 
let sayHi = sayHello; // sayHi is now a reference to the sayHello function 

summation = sum(2, 3); // 5 
sayHi(); // Hello, world!

ابتدا به تابع add() توجه کنید. این تابع، مجموع دو آرگومانش را برمی‌گرداند. وقتی این تابع را به همراه پرانتز یعنی به فرم add() به یک متغیر بدهیم، مقدار خروجی این تابع در متغیر قرار می‌گیرد. بنابراین، در مثال بالا مقدار 8 در متغیر summation ذخیره می‌شود. اما وقتی تابع را بدون پرانتز یعنی به فرم add به یک متغیر دیگر بدهیم، خودِ تابع در متغیر دیگر قرار می‌گیرد و بنابراین، همانطور که در کد بالا کامنت شده، متغیر sum یک ارجاع به تابع add() خواهد بود و از این به بعد، به جای add() می‌توان از sum() هم استفاده کرد.

اما در مورد تابع sayHello() چون این تابع مقداری برنمی‌گرداند، تخصیص آن به همراه پرانتز به متغیر greeting باعث می‌شود که مقدار undefined در این متعیر ذخیره شود.

حالا به مثال زیر توجه کنید که در آن از سینتکس Function Expression برای تعریف توابع استفاده شده است.

Copy Icon functions.js
let sum = function(a, b) {
  return a + b;
};

let sayHi = function() {
  console.log("Hello, world!");
};

console.log(sum(2, 3)); // 5 
sayHi(); // Hello, world!

د اینجا هم مثل مثال قبل، متغیرهای sum و sayHi یک تابع را به عنوان مقدار دریافت کرده‌اند منتها با این تفاوت که این توابع از قبل تعریف نشده‌اند، بلکه تعریف آنها با استفاده از سینتکس Runction Expression صورت گرفته است. طبیعتاً در این روش، توابع به نام نیازی ندارند؛ چون مستقیماً به یک متغیر تخصیص داده می‌شوند.

پس، از آنجایی که توابع حکم مقدار را دارند، می‌توانیم یک تابع را به یک متغیر تخصیص بدهیم. حالا این تابع می‌تواند از قبل تعریف شده باشد یا با سینتکس Function Expression در یک مرحله تعریف و تخصیص شود.

تابع به عنوان آرگومان

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

Copy Icon functions.js
function greet(name, callback) {
  console.log("Hello, " + name);
  callback();
}
          
function sayGoodbye() {
  console.log("Goodbye!");
}
          
greet("Alice", sayGoodbye);

کد بالا را می‌توانیم به صورت زیر هم بنویسیم که از سینتکمس Function Expression برای تعریف تابع Callback استفاده کرده است.

Copy Icon functions.js
function greet(name, callback) {
  console.log("Hello, " + name);
  callback();
}

greet("Alice", function() {
  console.log("Goodbye!");
});

در این مثال، تابع greet() یک نام و یک تابع را به عنوان آرگومان می‌پذیرد. این تابع ابتدا پیامی را به همراه نام دریافتی چاپ می‌کند و سپس تابع Callback را فراخوانی می‌کند. در این مثال، تابع sayGoodbye() به عنوان تابع Callback به تابع greet() ارسال شده است. این تابع Callback در اینجا یک تابع بدون نام است که به صورت مستقیم در مکان فراخوانی تابع greet() تعریف شده است.

تابع به عنوان خروجی

در جاوااسکریپت توابع می‌توانند یک تابع دیگر را به عنوان مقدار خروجی خود برگردانند و این موضوع هم از این حقیقت ناشی می|‌شود که توابع جاوااسکریپت حکم مقدار را دارند. به مثال زیر دقت کنید.

Copy Icon functions.js
function multiplier(factor) {
  return function(number) {
      return number * factor;
  };
}
          
const double = multiplier(2);  // Returns a function that multiplies by 2
const triple = multiplier(3);  // Returns a function that multiplies by 3
          
console.log(double(5));  // Output: 10
console.log(triple(5));  // Output: 15

با کاربرد این تکنیک در فصل دهم و پس از آشنایی با مفهوم Closure بیشتر آشنا خواهیم شد.