گام به گام با ES6 – Generator
تا الان برایتان سوال شده که آیا میشود یک تابع را هنگام اجرا متوقف کرد و اجرای ادامهی آن را به بعد موکول کرد؟ جدا از اینکه این کار چه فایدهای دارد، در این مقاله قصد داریم قابلیتی به اسم generator را معرفی کنیم که در ES6 وارد جاوااسکریپت شده و انجام این کار را برای ما میسر میکند. البته موارد استفاده از generator فقط به این تعریف محدود نمیشود، ولی به دلیل ماهیت نیمه پیچیدهای که دارد وارد این مباحث نمیشویم. با ما همراه باشید تا با تعریفی اولیه از generatorها آشنا شویم.
نحوهی تعریف و استفاده
برای تعریف کردن generator مثل تابع عادی عمل میکنیم با این تفاوت که بعد از کلمهی function علامت * میگذاریم.
function* first() { }
اما استفاده از generator مثل استفاده از تابع نیست. مثال زیر را ببینید:
function* first() { yield 'test'; } const gen = first(); console.log(gen.next()); // {value: "test", done: false} console.log(gen.next()); // {value: undefined, done: true}
برای استفاده از generator باید اول متغیری ایجاد کنیم و مقدار برگشتی از تابع generator را درون آن بریزیم(تقریبا شبیه ساخت شیء از روی کلاس) و سپس با استفاده از متد next مرحله به مرحله در تابع به جلو برویم و مقدار بازگشتی از آن مرحله را تحویل بگیریم. شاید این تکه از متن یک مقدار گنگ به نظر بیاید، ولی با اجرای کد بالا و دیدن خروجی، تا حد زیادی این گنگی از بین میرود(البته خروجیها به صورت comment جلوی دو خط آخر نوشته شدهاند). این را هم فراموش نکنید که به خاطر ظاهر غیر ملموس generator ارتباط برقرار کردن با آن مقداری مشکل هست.
در کد بالا در خط ۲ یک قسمت جدید دیگر هم میبینیم. با استفاده کلمهی yield میتوانیم نقطههای توقف generator را مشخص کنیم. بار اولی که gen.next را نوشتیم، generator تا اولین yield (یعنی خط ۲) اجرا شد، بار دومی که gen.next را نوشتیم اجرای generator تا yield بعدی ادامه پیدا میکند ولی به دلیل اینکه yield دیگری وجود ندارد، generator تا آخر اجرا میشود و خاتمه مییابد. مثال زیر به واضح شدن این بخش کمک میکند:
function* first() { yield 'test'; console.log('between inside generator'); yield 'test2'; console.log('end generator'); } const gen = first(); console.log(gen.next()); console.log('between outside generator'); console.log(gen.next()); console.log(gen.next());
روند کار در کد بالا به ترتیب زیر است:
- در خط ۷ یک generator داریم که آمادهی استفاده است.
- طبق روند عادی برنامه، خط ۸ اجرا میشود. در خط ۸ گفتیم که generator را تا اولین yield اجرا کن یعنی فقط خط ۲ اجرا میشود.
- کنترل برنامه بعد از رسیدن به yield به مکان قبلی خود یعنی خط ۸ برمیگردد و مقدار بازگشتی از این مرحله(یعنی objectی که عبارت test در قسمت value آن قرار دارد) را چاپ میکند. و طبق روند عادی به خط بعد یعنی خط ۹ میرود.
- بعد از خط ۹ نوبت خط ۱۰ است که اجرا شود. در خط ۱۰ دوباره gen.next داریم، یعنی از آنجایی که کار generator را رها کردی شروع به کار کن و تا yield بعدی ادامه بده. یعنی خط ۳ و ۴ اجرا میشوند.
- بعد از این کار کنترل برنامه به خط ۱۰ برمیگردد و مقدار بازگشتی از این مرحله(یعنی objectی با مقدار valueی برابر test2) نیز چاپ میشود. بعد از خط ۱۰ خط ۱۱ اجرا میشود و دوباره عبارت gen.next داریم و برنامه اجرای generator را از همان نقطهای که generator را رها کرد(یعنی خط ۴) ادامه میدهد و خط ۵ را اجرا میکند و چون yield دیگری وجود ندارد، کار generator پایان مییابد و مقدار done در object بازگشتی برابر true میشود.
همچنین میتوانیم علاوه بر برگشت دادن مقدار از generator، مقداری را نیز به عنوان ورودی به آن بدهیم. مثال زیر را ببینید:
function* first() { let num = yield 'test'; console.log(num); } const gen = first(); console.log(gen.next()); console.log(gen.next(2));
در مثال بالا عدد ۲ را به generator فرستادیم و این مقدار به جای yield مورد نظر قرار گرفت و در متغیر num نوشته شد، سپس متغیر num را چاپ کردیم.
استفاده از حلقهی for…of
یکی از مکانهایی که در آن میتوانیم از generatorها استفاده کنیم، حلقهی for…of است. مثال زیر را ببینید تا با نحوهی کاربرد این حلقه آشنا شوید:
function* first() { yield 1; yield 2; yield 3; } for (let f of first()) { console.log(f); }
کد بالا به ترتیب اعداد ۱ و ۲ و ۳ را چاپ میکند. با استفاده از حلقهی for…of لازم نیست تا ۴ بار gen.next بنویسیم تا تمام مراحل generator طی شوند. کاری که این حلقه بر روی generatorها انجام میدهد مانند کاریست که حلقهی for بر روی آرایهها انجام میدهد.
در آخر دوباره یادآوری این نکته حائز اهمیت است که شاید باز کردن جا برای استفاده از generator در کدهایی که نوشتیم سخت باشد ولی با تمرین و استفاده از این قابلیت ES6 به زودی و بدون آنکه حتی متوجه شویم شاهد حضور آن در جای جای کد خود میشویم.
مطالب زیر را حتما مطالعه کنید
جاوا اسکریپت چیست؟
متدهایی از جاوا اسکریپت که مهارت های شما را بالا می برد!
5 ترفند css3 با عناصر کاذب before:: و after::
آشنایی با Protobuf
7 ویژگی Sass به همراه کد
شروع کار با Sass
1 Comment
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
ایول تو مایه های پایتون داره میشه….