یکی از اهداف
ES 6، استاندارد سازی کار با Iterators و Iterables است. فرض کنید شیءایی را داریم که مجموعهای از عناصر را در بر دارد. این مجموعه میتواند آرایهای از عناصر باشد و یا set و map اضافه شده به ES 6 و یا حتی اشیایی که در زمان اجرا ایجاد میشوند. اگر این مجموعه Iterable باشد، حرکت بر روی آن یک Iterator را تولید میکند که امکان حرکت در این مجموعه را آیتم به آیتم میسر خواهد کرد:
هر Iterator شیءایی است که دارای متد next میباشد. هر بار که این متد فراخوانی میشود، عضو بعدی مجموعه، بازگشت داده خواهد شد. خروجی هر مرحله، درون یک شیء با دو خاصیت value و done قرار داده میشود. value، مقدار مرحلهی بعد است و done مشخص میکند که آیا به پایان مجموعه رسیدهایم یا خیر (بنابراین در اینجا تعداد اعضای Iterator مشخص نیست).
مثالی از پیمایش یک آرایه با چندین روش مختلف
در مثال زیر، آرایهای از اعداد را داریم که نیاز است جمع اعضای آن محاسبه شود:
let sum = 0;
let numbers = [1,2,3,4];
اینکار را میتوان با استفاده از یک حلقهی for متداول انجام داد. از آنجائیکه آرایه دارای خاصیت length است، میتوان از آن جهت تعیین حد بالایی آرایه استفاده کرد:
// for loop
sum = 0;
for(let i =0; i < numbers.length; i++){
sum += numbers[i];
}
//sum = 10
روش دوم انجام اینکار، استفاده از حلقهی for in است. این حلقه هربار ایندکس بعدی قابل استفادهی آرایه را بازگشت میدهد که از آن میتوان جهت دسترسی به اعضای آرایه استفاده کرد:
// for in
sum = 0;
for(let i in numbers) {
sum += numbers[i];
}
//sum = 10
روش دیگر انجام اینکار با استفاده از Iterators است:
// iterator
sum = 0;
let iterator = number.values();
let next = iterator.next();
while(!next.done){
sum += next.value;
next = iterator.next();
}
//sum = 10
برای کار با Iterators، ابتدا باید یک شیء Iterator را از مجموعهایی که در اختیار داریم، تولید کنیم. برای مثال آرایهها دارای متدی به نام values هستند که با فراخوانی ()number.values، سبب تولید یک Iterator میشوند. این Iterator امکان حرکت بین مقادیر آرایه را در اینجا میسر میکند.
مرحلهی بعدی، فراخوانی متد next این Iterator است. این عملیات باید در طی یک حلقه، تا پایان کار Iterator انجام شود. همانطور که در ابتدای بحث نیز عنوان شد، خروجی متد next یک شیء است که دارای خواص value و done میباشد. اگر done مساوی true شد، یعنی به پایان کار پیمایش رسیدهایم.
البته هدف از این مثال، صرفا نمایش سطح پایین کار با Iterators بود. در عمل از حلقهی جدیدی به نام for of برای انجام این پیمایش استفاده میشود.
معرفی حلقهی for of
جاوا اسکریپت سالها است که دارای حلقهی for in میباشد و نمونهای از کاربرد آنرا در مثال قبل مشاهده کردید. اگر این حلقه بر روی آرایهها فراخوانی شود، هربار ایندکس پیمایش شده را بازگشت میدهد و اگر بر روی یک شیء فراخوانی شود، خواص آن شیء را بازگشت میدهد:
var person = { first: "Vahid", last "N" };
for(let i in person) {
console.log(person[i]);
}
در این مثال، i بار اول به first و بار دوم به خاصیت last اشاره میکند.
چون این حلقه صرفا ایندکسها و کلیدها را بازگشت میدهد، جهت کار با Iterators که نیاز است به مقادیر اعضاء دسترسی پیدا کنیم، مناسب نیست. به همین جهت در
ES 6، حلقهی جدیدی به نام for of برای کار با Iterators معرفی شدهاست:
let numbers = [1,2,3,4];
for(let i of numbers) {
console.log(i);
}
این حلقه برخلاف for in، بر روی values، کار پیمایش را انجام میدهد. همچنین به صورت خودکار در پشت صحنه متد next یک Iterator را فراخوانی میکند و خاصیت done آنرا بررسی کرده و زمانیکه این خاصیت مساوی true شد، حلقه را خاتمه میدهد. برای نمونه مثال سطح پایین while دار ابتدای بحث را به نحو سادهتری با حلقهی for of ذیل میتوان جایگزین کرد:
let sum = 0;
let numbers = [1,2,3,4];
for(let n of numbers){
sum += n;
}
for of یکی از روشهای پیمایش Iterators است.
پارامترهای rest و همچنین
Array.from نیز چنین قابلیتی را فراهم میکنند.
امکان پیاده سازی Iterators سفارشی نیز وجود دارد که پیشنیاز آن، درک مبحث جدید Symbols است که به صورت جداگانهای بررسی خواهد شد.