پیمایش و تبدیل آرایه با متدهای تکرارکننده

مقدمه

در درس‌های قبل با حلقه‌ی for...of برای پیمایش آرایه آشنا شدیم. اما جاوااسکریپت مجموعه‌ای از متدهای تخصصی‌تر و خواناتر ارائه می‌دهد که به آن‌ها متدهای تکرارکننده (Iteration Methods) می‌گویند. این متدها امروزه در کدنویسی مدرن جاوااسکریپت بسیار پرکاربردتر از حلقه‌های سنتی هستند.

forEach — اجرای یک عملیات روی هر عنصر

let numbers = [1, 2, 3];

numbers.forEach(function (num) {
  console.log(num * 2);
});
// خروجی: 2 4 6

forEach یک تابع (Callback) دریافت می‌کند و آن را برای تک‌تک عناصر آرایه اجرا می‌کند. برخلاف for...of، forEach هیچ مقداری بازنمی‌گرداند (همیشه undefined) و نمی‌توان با break آن را متوقف کرد.

map — ساخت یک آرایه‌ی جدید با تبدیل هر عنصر

تبدیل عناصر آرایه با map
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل کد

map برای هر عنصر آرایه، تابع Callback را اجرا می‌کند و مقدار بازگشتی آن را در یک آرایه‌ی جدید قرار می‌دهد. تعداد عناصر آرایه‌ی خروجی همیشه برابر با آرایه‌ی ورودی است. برخلاف forEach، آرایه‌ی اصلی (numbers) هیچ تغییری نمی‌کند؛ map همیشه یک آرایه‌ی جدید برمی‌گرداند.

filter — انتخاب عناصری که شرط خاصی دارند

let numbers = [1, 2, 3, 4, 5, 6];

let evens = numbers.filter(function (num) {
  return num % 2 === 0;
});

console.log(evens); // [2, 4, 6]

filter برای هر عنصر، تابع Callback را اجرا می‌کند؛ اگر مقدار بازگشتی Truthy باشد، آن عنصر در آرایه‌ی خروجی نگه داشته می‌شود، در غیر این صورت حذف می‌شود. تعداد عناصر آرایه‌ی خروجی می‌تواند کمتر یا مساوی آرایه‌ی ورودی باشد.

find — پیدا کردن اولین عنصر مطابق با شرط

let users = [
  { name: "علی", age: 25 },
  { name: "سارا", age: 30 },
  { name: "رضا", age: 35 }
];

let found = users.find(function (user) {
  return user.age > 28;
});

console.log(found); // { name: "سارا", age: 30 }

find برخلاف filter، به‌محض یافتن اولین عنصری که شرط را برآورده کند، متوقف می‌شود و همان یک عنصر (نه آرایه) را برمی‌گرداند. اگر هیچ عنصری با شرط مطابقت نداشته باشد، مقدار undefined بازگردانده می‌شود.

reduce — تبدیل آرایه به یک مقدار واحد

reduce پیچیده‌ترین اما قدرتمندترین متد این گروه است؛ تمام عناصر آرایه را پردازش کرده و آن‌ها را به یک مقدار واحد تبدیل می‌کند:

جمع کردن عناصر با reduce
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل رفتار جاوااسکریپت

reduce دو آرگومان می‌گیرد: یک تابع Callback و یک مقدار اولیه (در اینجا 0). تابع Callback خودش دو پارامتر اصلی دارد: accumulator (مقدار انباشته‌شده تا این لحظه) و current (عنصر فعلی آرایه). در هر مرحله، مقدار بازگشتی Callback به‌عنوان accumulator مرحله‌ی بعد استفاده می‌شود؛ در پایان، مقدار نهایی accumulator از reduce بازگردانده می‌شود.

اگر مقدار اولیه (آرگومان دوم reduce) داده نشود، جاوااسکریپت اولین عنصر آرایه را به‌عنوان مقدار اولیه در نظر می‌گیرد و پیمایش را از عنصر دوم شروع می‌کند؛ اما توصیه می‌شود همیشه مقدار اولیه را صریح مشخص کنید تا رفتار کد قابل پیش‌بینی‌تر باشد.

some و every — بررسی گروهی عناصر

let numbers = [1, 2, 3, 4, 5];

console.log(numbers.some(function (n) { return n > 4; }));  // true — حداقل یکی بزرگ‌تر از 4 است
console.log(numbers.every(function (n) { return n > 0; })); // true — همه بزرگ‌تر از 0 هستند
console.log(numbers.every(function (n) { return n > 4; })); // false — همه بزرگ‌تر از 4 نیستند

some بررسی می‌کند که آیا حداقل یک عنصر شرط را برآورده می‌کند، و every بررسی می‌کند که آیا تمام عناصر شرط را برآورده می‌کنند. هر دو یک مقدار Boolean برمی‌گردانند.

جدول مقایسه‌ی متدهای تکرارکننده

متدخروجیکاربرد اصلی
forEachundefinedاجرای یک عملیات روی هر عنصر
mapآرایه‌ی جدید (هم‌طول)تبدیل هر عنصر
filterآرایه‌ی جدید (کوتاه‌تر یا مساوی)انتخاب عناصر مطابق شرط
findیک عنصر یا undefinedپیدا کردن اولین عنصر مطابق شرط
reduceیک مقدار واحدتبدیل آرایه به یک مقدار
some / everyBooleanبررسی گروهی شرط

Best Practices

  • برای تبدیل عناصر آرایه، همیشه map را به‌جای forEach با push دستی به یک آرایه‌ی دیگر ترجیح دهید.
  • برای reduce، همیشه مقدار اولیه را صریح مشخص کنید تا از رفتار غیرمنتظره در آرایه‌های خالی جلوگیری شود.
  • وقتی فقط به یک عنصر خاص نیاز دارید، از find استفاده کنید، نه filter به همراه گرفتن اندیس صفر.

ارتباط با سایر مفاهیم

تمام این متدها نمونه‌ای از Higher-Order Functions هستند؛ یعنی توابعی که تابع دیگری را به‌عنوان آرگومان می‌پذیرند. این مفهوم را با جزئیات کامل در فصل توابع پیشرفته بررسی خواهیم کرد. همچنین، Arrow Function که در فصل قبل دیدیم، معمولاً برای نوشتن کوتاه‌تر Callback این متدها استفاده می‌شود.

جمع‌بندی

متدهای تکرارکننده‌ی آرایه، ابزارهای خوانا و استانداردی برای پردازش داده هستند: forEach برای اجرای عملیات ساده، map برای تبدیل عناصر، filter برای انتخاب عناصر مطابق شرط، find برای یافتن یک عنصر خاص، reduce برای تبدیل آرایه به یک مقدار واحد، و some/every برای بررسی گروهی شرط‌ها. این متدها امروزه جایگزین اصلی حلقه‌های سنتی در بسیاری از سناریوها هستند.