درس ۱۵: توابع
یادگیری توابع JavaScript برای سازماندهی و استفاده مجدد کد
توابع چیستند؟
توابع (Functions) یکی از مهمترین مفاهیم در JavaScript هستند. تابع بلوکی از کد است که برای انجام یک کار خاص طراحی شده و میتواند چندین بار فراخوانی شود. توابع به شما کمک میکنند کد خود را سازماندهی کرده و از تکرار جلوگیری کنید.
مزایای استفاده از توابع:
- قابلیت استفاده مجدد کد (Reusability)
- سازماندهی بهتر کد
- تست و دیباگ آسانتر
- کاهش پیچیدگی برنامه
- تقسیم کار به بخشهای کوچکتر
تعریف توابع
۱. Function Declaration
روش کلاسیک تعریف تابع:
function sayHello() {
console.log("سلام دنیا!");
}
// فراخوانی تابع
sayHello();
۲. Function Expression
تعریف تابع به عنوان یک عبارت:
const greet = function() {
console.log("خوش آمدید!");
};
greet();
۳. Arrow Functions
روش مدرن و کوتاهتر تعریف تابع:
const welcome = () => {
console.log("به سایت ما خوش آمدید!");
};
welcome();
تمرین عملی: انواع توابع
در ادامه، انواع مختلف توابع و کاربردهای آنها را مشاهده کنید:
ویرایشگر کد
خط 1، ستون 1
نمایش زنده
پارامترها و آرگومانها
پارامترهای ساده
function introduce(name, age, city) {
return `سلام، من ${name} هستم، ${age} سال دارم و در ${city} زندگی میکنم.`;
}
console.log(introduce("علی", 25, "تهران"));
مقادیر پیشفرض
function greetUser(name = "کاربر", time = "روز") {
return `${time} بخیر ${name}!`;
}
console.log(greetUser()); // "روز بخیر کاربر!"
console.log(greetUser("سارا", "شب")); // "شب بخیر سارا!"
Rest Parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
مقادیر برگشتی
Return ساده
function calculateArea(width, height) {
return width * height;
}
const area = calculateArea(10, 5);
console.log("مساحت:", area); // 50
Return چندگانه
function getPersonInfo(name, age) {
return {
fullName: name,
years: age,
isAdult: age >= 18,
category: age < 13 ? "کودک" : age < 18 ? "نوجوان" : "بزرگسال"
};
}
const person = getPersonInfo("مریم", 22);
console.log(person);
Early Return
function validateAge(age) {
if (age < 0) {
return "سن نمیتواند منفی باشد";
}
if (age > 150) {
return "سن غیرمعقول است";
}
return "سن معتبر است";
}
محدوده متغیرها (Scope)
Global Scope
let globalVar = "من متغیر سراسری هستم";
function showGlobal() {
console.log(globalVar); // قابل دسترسی
}
showGlobal();
Function Scope
function myFunction() {
let localVar = "من متغیر محلی هستم";
console.log(localVar); // قابل دسترسی
}
myFunction();
// console.log(localVar); // خطا! غیرقابل دسترسی
Block Scope
function testScope() {
if (true) {
let blockVar = "متغیر بلوک";
const blockConst = "ثابت بلوک";
console.log(blockVar); // قابل دسترسی
}
// console.log(blockVar); // خطا! غیرقابل دسترسی
}
Arrow Functions
ساختار کوتاه
// تابع معمولی
function square(x) {
return x * x;
}
// Arrow function
const square = x => x * x;
// Arrow function با چند پارامتر
const add = (a, b) => a + b;
// Arrow function با بدنه
const processData = (data) => {
const processed = data.map(x => x * 2);
return processed.filter(x => x > 10);
};
تفاوتهای مهم
⚠️ نکات مهم Arrow Functions:
- ندارای
this
مخصوص به خود - نمیتوان به عنوان constructor استفاده کرد
- ندارای
arguments
object - نمیتوان hoisted شوند
مفاهیم پیشرفته
Higher Order Functions
توابعی که توابع دیگر را به عنوان پارامتر میگیرند یا تابع برمیگردانند:
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(4)); // 12
Callback Functions
function processArray(array, callback) {
const result = [];
for (let item of array) {
result.push(callback(item));
}
return result;
}
const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
Closure
function createCounter(initialValue = 0) {
let count = initialValue;
return {
increment: () => ++count,
decrement: () => --count,
getValue: () => count,
reset: () => count = initialValue
};
}
const counter = createCounter(10);
console.log(counter.increment()); // 11
console.log(counter.getValue()); // 11
بهترین شیوهها
💡 نکات مهم:
- نامگذاری: از نامهای توصیفی استفاده کنید
- اندازه: توابع کوچک و تکمنظوره بنویسید
- پارامترها: تعداد پارامترها را محدود کنید
- مستندسازی: توابع پیچیده را مستند کنید
- تست: توابع را به صورت جداگانه تست کنید
مثال تابع بهینه
/**
* محاسبه قیمت نهایی با احتساب تخفیف و مالیات
* @param {number} basePrice - قیمت پایه
* @param {number} discountPercent - درصد تخفیف (0-100)
* @param {number} taxPercent - درصد مالیات (0-100)
* @returns {number} قیمت نهایی
*/
function calculateFinalPrice(basePrice, discountPercent = 0, taxPercent = 9) {
// اعتبارسنجی ورودی
if (basePrice < 0) throw new Error("قیمت نمیتواند منفی باشد");
if (discountPercent < 0 || discountPercent > 100) {
throw new Error("تخفیف باید بین 0 تا 100 باشد");
}
// محاسبه قیمت با تخفیف
const discountAmount = basePrice * (discountPercent / 100);
const priceAfterDiscount = basePrice - discountAmount;
// محاسبه مالیات
const taxAmount = priceAfterDiscount * (taxPercent / 100);
const finalPrice = priceAfterDiscount + taxAmount;
return Math.round(finalPrice * 100) / 100; // گرد کردن به 2 رقم اعشار
}
آزمون درس ۱۵
سوال ۱: کدام روش تعریف تابع hoisting ندارد؟
سوال ۲: خروجی این کد چیست؟
function test(a = 5, b = 10) {
return a + b;
}
console.log(test(3));