گردش (iteration) در آرایه های جاوا اسکریپت

16 بهمن 1397
javascript-iteration

با سلام، مبحث iteration (به معنی تکرار یا گردش) در آرایه ها مبحثی بسیار ساده است که اگر به جزئیات آن توجه کنید یاد گرفتنش بیش از نیم تا یک ساعت طول نخواهد کشید.

اگر یادتان باشد آرایه ها در جاوا اسکریپت نوع خاصی از متغیر ها بودند که می توانستند بر خلاف دیگر متغیر ها، چندین مقدار یا عضو را در خود ذخیره کنند. یک مثال از آرایه ها را در کد زیر می بینید:

var cars = [
  "Saab",
  "Volvo",
  "BMW"
];

این کد با کد زیر هیچ تفاوتی ندارد و هر دو یک آرایه ی یکسان و مشابه هستند:

var cars = ["Saab", "Volvo", "BMW"];

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

منظور من، تغییر یکی از اعضای آرایه و ... نیست، بلکه پردازش یا تغییری بزرگ روی تمام اعضای آرایه ها است. در این جلسه با این متد ها آشنا خواهیم شد.

دستور ()forEach

عبارت forEach (به شکل بهتر: For Each) به معنی "برای هر کدام" است. به عبارت دیگر این دستور می گوید برای هر کدام از اعضای آرایه فلان کار را انجام بده. به کد زیر توجه کنید:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.forEach()</h2>

<p>Calls a function once for each array element.</p>

<p id="demo"></p>

<script>
var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);
document.getElementById("demo").innerHTML = txt;

function myFunction(value, index, array) {
  txt = txt + value + "<br>"; 
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

همانطور که میبینید در این کد گفته ایم برای هر عضو آرایه (همان اعداد داخل آرایه) یک تابع به نام myFunction را اجرا کن. سپس پایین تر این تابع را تعریف کرده ایم و گفته ایم که مقادیر را تک تک چاپ کند.

حتما متوجه شده اید که تابع myfunction تنها از پارامتر value استفاده می کند و سایر پارامترها قابل استفاده نیستند.

ما تنها برای یادگیری شما کد را چنین نوشته ایم تا اگر شما لازم داشتید به مقادیر دیگری دسترسی داشته باشید.

بنابراین این کد را می توان به شکل زیر نیز نوشت:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.forEach()</h2>

<p>Calls a function once for each array element.</p>

<p id="demo"></p>

<script>
var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);
document.getElementById("demo").innerHTML = txt;

function myFunction(value) {
  txt = txt + value + "<br>"; 
}
</script>

</body>
</html>

پشتیبانی از foreach در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()map

این دستور با اجرای یک تابع روی تک تک اعضای آرایه، یک آرایه ی جدید می سازد. البته باید توجه داشت که این دستور تابع مورد نظر را روی اعضای بدون مقدار اجرا نمی کند و آرایه ی اصلی را نیز تغییر نمی دهد. به مثال زیر توجه کنید:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.map()</h2>

<p>Creates a new array by performing a function on each array element.</p>

<p id="demo"></p>

<script>
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

document.getElementById("demo").innerHTML = numbers2;

function myFunction(value, index, array) {
  return value * 2;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

کد بالا با استفاده از دستور ()map (به معنای مپ کردن یا مپینگ در علوم کامپیوتری) مقادیر موجود در تابع را دو برابر می کند و سپس نمایش می دهد.

مانند مثال قبل، آرایه پارامتر های بیشتری می گیرد که از آن ها استفاده نمی کند بنابراین می توان آن را به صورت زیر خلاصه نویسی کرد:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.map()</h2>

<p>Creates a new array by performing a function on each array element.</p>

<p id="demo"></p>

<script>
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

document.getElementById("demo").innerHTML = numbers2;

function myFunction(value) {
  return value * 2;
}
</script>

</body>
</html>

پشتیبانی از map در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()filter

دستور ()filter (به معنی فیلتر کردن) اعضای یک آرایه را بر اساس نوعی تست دلخواه می سنجد و در صورت پذیرفته شدن، با همان اعضا یک آرایه ی جدید می سازد. به طور مثال کد زیر با اعضایی که مقدارشان بیشتر از 18 است یک آرایه ی جدید می سازد:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.filter()</h2>

<p>Creates a new array with all array elements that passes a test.</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

document.getElementById("demo").innerHTML = over18;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

مانند مثال قبل باید بگویم که پارامتر های اضافی تنها برای گسترش یادگیری شماست تا بدانید به آن ها نیز دسترسی دارید. در صورتی که استفاده ای برای شما ندارند می توانید آن ها را حذف کنید (بنده به دلیل ساده بودن کار، از تکرار کد ها پرهیز می کنم).

پشتیبانی از filter در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()reduce

دستور ()reduce (به معنی کاهش دادن یا کوتاه کردن) تابعی را روی تک تک اعضای آرایه اجرا می کند تا یک مقدار نهایی را تولید کند.

باید بدانید که این دستور از چپ به راست کار می کند (برای کار کردن از راست به چپ دستور بعدی را ببینید) و خود آرایه را تغییر نمی دهد.

این دستور در مثال زیر مقادیر آرایه را جمع می زند و یک مقدار واحد را تحویل ما می دهد:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.reduce()</h2>

<p>This example finds the sum of all numbers in an array:</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var sum = numbers.reduce(myFunction);

document.getElementById("demo").innerHTML = "The sum is " + sum;

function myFunction(total, value, index, array) {
  return total + value;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

سوال: مگر نام این تابع به معنی کاهش نبود؟ چطور شد که مقادیر را جمع زد؟

پاسخ: کاهش دادن، اشاره به کاهش دادنِ تعداد اعضای آرایه دارد (حالا از هر راهی باشد، چه ضرب، چه جمع و ...) نه اشاره به مقدار کل آرایه.

نکته: منظور از پارامتر total که در تابع می بینید، مقدار اولیه یا مقداری است که تابع قبلی به ما داده است. از آنجایی که ما در این مثال نیازی به آن نداریم می توانیم پارامتر های غیر ضروری را حذف کنیم:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.reduce()</h2>

<p>This example finds the sum of all numbers in an array:</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var sum = numbers.reduce(myFunction);

document.getElementById("demo").innerHTML = "The sum is " + sum;

function myFunction(total, value) {
  return total + value;
}
</script>

</body>
</html>

اما اگر خواستید از مقدار اولیه استفاده کنید می توانید آن را باقی بگذارید. مثال:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.reduce()</h2>

<p>This example finds the sum of all numbers in an array:</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var sum = numbers.reduce(myFunction, 100);

document.getElementById("demo").innerHTML = "The sum is " + sum;

function myFunction(total, value) {
  return total + value;
}
</script>

</body>
</html>

خروجی این کد عدد 199 می باشد چرا که 100 را به عنوان مقدار اولیه به تابع پاس دادیم.

پشتیبانی از reduce در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()reduceRight

دستور ()reduceRight (به معنی کاهش دادن یا کوتاه کردن از سمت راست) دقیقا مشابه متد فوق می باشد (reduce) اما تفاوتش آنجاست که از راست به چپ کار می کند.

اگر یادتان باشد در قسمت قبلی گفتیم که متد reduce عملیاتِ روی مقادیر را (چه ضرب باشد، چه جمع، چه تفریق و ...) از سمت چپ به راست انجام می دهد اما این تابع این کار را از سمت راست به چپ انجام می دهد.

در نظر داشته باشید که این دستور، آرایه ی اصلی را تغییر نمی دهد.

مثال:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.reduceRight()</h2>

<p>This example finds the sum of all numbers in an array:</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var sum = numbers.reduceRight(myFunction);

document.getElementById("demo").innerHTML = "The sum is " + sum;

function myFunction(total, value, index, array) {
  return total + value;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

پشتیبانی از ()reduceRight در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()every

دستور ()every (به معنای "همه") چک می کند که تمام اعضای آرایه، یک تست مشخص را پاس کنند. کد زیر چک می کند تا ببیند آیا تمام اعضای آرایه بیشتر از 18 هستند یا خیر:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.every()</h2>

<p>The every() method checks if all array values pass a test.</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);

document.getElementById("demo").innerHTML = "All over 18 is " + allOver18;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

نکته ی مهم: این دستور را با دستور ()filter اشتباه نگیرید! دستور ()filter تک تک اعضای یک آرایه را با تستی مشخص می سنجید و با آن هایی که قبول می شدند یک آرایه ی جدید می ساخت. این متد تمام اعضا را می سنجد و در نهایت به شما یا true می دهد یا false!

برای مقایسه، پس از نگاه کردن به کد بالا، به یک مثال از متد filter توجه کنید:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.filter()</h2>

<p>Creates a new array with all array elements that passes a test.</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

document.getElementById("demo").innerHTML = over18;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

خروجی متد every مقدار "All over 18 is false" بود اما خروجی متد filter مقدار "45,25" بود!

پشتیبانی از ()every در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()some

دستور ()some (به معنی "برخی") این مسئله را چک می کند که آیا برخی از اعضای یک آرایه، تستی مشخص را پاس می کنند یا خیر. مثال زیر چک می کند که آیا برخی از اعضای آرایه بالای 18 سال هستند یا خیر:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.some()</h2>

<p>The some() method checks if some array values pass a test.</p>

<p id="demo"></p>

<script>
var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);

document.getElementById("demo").innerHTML = "Some over 18 is " + someOver18;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

پشتیبانی از ()some در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()indexOf

دستور ()indexOf(به معنی "ایندکسِ ...") یک آرایه را بر اساس یک مقدار خاص می گردد و سپس ایندکسِ آن مقدار را بر میگرداند:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.indexOf()</h2>


<p id="demo"></p>

<script>
var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
document.getElementById("demo").innerHTML = "Apple is found in position " + (a + 1);
</script>

<p>The indexOf() does not work in Internet Explorer 8 and earlier versions.</p>

</body>
</html>

مشاهده ی خروجی کد در ادیتور آنلاین جاوا اسکریپت

در مثال بالا به تابع مقدار "apple" را دادیم و خروجی آن عدد 1 خواهد بود که همان ایندکسِ apple است (یادتان باشد که ایندکس ها از صفر شروع می شوند).

ساختار کلی این تابع به شکل زیر است:

array.indexOf(item, start)
پارامتر اول همان مقدار است که در مثال قبل نیز مشاهده کردید و پارامتر دوم مکانی است که شما می خواهید جست و جو از آن جا شروع شود.
دو نکته:
  • اگر این تابع نتواند هیچ مقداری را پیدا کند عدد 1- را بر میگرداند.
  • اگر مقدار سرچ شده ی ما چندین بار وجود داشته باشد، تنها اولین مقداری که پیدا شود برگردانده می شود.

پشتیبانی از ()indexOf در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()lastIndexOf

دستور ()lastIndexOf (به معنی "آخرین ایندکسِ ...") دقیقا مشابه دستور قبلی است با این تفاوت که از آخرِ آرایه شروع به جست و جو می کند. مثال:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.lastIndexOf()</h2>


<p id="demo"></p>

<script>
var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple");
document.getElementById("demo").innerHTML = "Apple is found in position " + (a + 1);
</script>

<p>The lastIndexOf() does not work in Internet Explorer 8 and earlier versions.</p>

</body>
</html>

طبق انتظار ما خروجی عدد 3 خواهد بود.

ساختار کلی این تابع نیز مانند تابع قبل است و می توانید پارامتر دومی به آن بدهید تا از آن مکان شروع به جست و جو کند.

پشتیبانی از ()lastIndexOf در مرورگر های مختلف:

بله بله بله نسخه ی 9 به بعد بله

دستور ()find

دستور ()find (به معنی "پیدا کن") یک تست مشخص را روی اعضای آرایه اجرا می کند و اولین مقداری که این تست را پاس کند برمیگرداند. مثال زیر مقدار اولین عضوی را که بیشتر از 18 است برمیگرداند:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.find()</h2>

<p id="demo"></p>

<script>
var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);

document.getElementById("demo").innerHTML = "First number over 18 is " + first;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

خروجی این کد عدد 25 است.

پشتیبانی از ()find در مرورگر های مختلف:

از نسخه ی 32 از نسخه ی 8 از نسخه ی 25 از نسخه ی 12 از نسخه ی 45

دستور ()findIndex

دستور ()findIndex (به معنی "ایندکس را پیدا کن") دقیقا مانند دستور قبل است با این تفاوت که به جای مقدار عضو، ایندکس عضو پیدا شده را می دهد. مثال زیر مقدار اولین عضوی را که بیشتر از 18 است برمیگرداند:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Array.findIndex()</h2>

<p id="demo"></p>

<script>
var numbers = [4, 9, 16, 25, 29];
var first = numbers.findIndex(myFunction);

document.getElementById("demo").innerHTML = "First number over 18 has index " + first;

function myFunction(value, index, array) {
  return value > 18;
}
</script>

</body>
</html>

خروجی این کد عبارت "First number over 18 has index 3" است یعنی اولین شماره (عضوی) که بیشتر از 18 است دارای ایندکس 3 می باشد.

پشتیبانی از ()findIndex در مرورگر های مختلف:

از نسخه ی 32 از نسخه ی 8 از نسخه ی 25 از نسخه ی 12 از نسخه ی 45

امیدوارم از این قسمت لذت برده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش جاوا اسکریپت | Javascript توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.