آموزش ویژگی های ECMAScript 6 (جلسه 34) : آموزش کار با Generator - قسمت 2

- visibility ۲ mode_comment

همونطور که اطلاع دارید در جلسه قبل بحث مربوط به Generator ها رو شروع کردیم و شما رو بصورت مقدماتی با اونا آشنا کردیم. در این جلسه میخوایم کار با Generator ها رو ادامه بدیم و هر چیزی که نیاز دارید رو در اختیارتون قرار بدیم.

همونطور که دیدید در مثال جلسه قبل دیدیم که یک تابع سازنده یا Generator با استفاده از 3 بار yield، حروف انگلیسی رو برگشت میده. وقتی که اون تابع رو فراخوانی کردیم، یک iterator در اختیارمون قرار گرفت و اون رو درون یک متغیر ذخیره کردیم. زمانی که 3 بار متد next رو برای این iterator صدا زدیم، هر بار یکی از حروف نمایش داده میشد. در نهایت و بعد از 3 بار استفاده از next، اگر از next مجددا استفاده کنیم undefined برگشت داده میشه. زمانی که در توابع سازنده، return رو در آخر تعریف نمی کنیم، بصورت ضمنی یک return undefined در انتهای تابع قرار میگیره. اما فرض کنید که خودمون از return استفاده کنیم و مقدار دیگه ای رو برگشت بدیم. کد زیر رو در نظر بگیرید:

میبینید که این بار از return استفاده کردیم و یک رشته رو برگشت دادیم. خروجی در مرورگر بصورت زیر میشه:

همونطور که میبینید مقدار finished مقابل value قرار گرفته و done نیز برابر با true است. به معنای اینه که تکرار iterator به پایان رسیده است.

ساخت شمارنده ساده با Generator

شما میتونین با استفاده از Generator ها هر نوع شمارنده ساده و پیشرفته ای رو به وجود بیارید و در هر زمان که بخواید به مقدار اون اضافه کنید. کد زیر رو در نظر بگیرید:

همونطور که میبینید یک تابع سازنده بنام countMaker به وجود آوردیم و با استفاده از حلقه while تا زمانی که مقدار count کمتر از 4 باشد، یکی به اون اضافه میکنیم و اون رو yield میکنیم. با اینکار هر بار که از متد next برای iterator ساخته شده از تابع سازنده استفاده میشه، شرط درون حلقه بررسی میشه و اگر کمتر از 4 باشه، یکی به میزان count اضافه شده و برگشت داده میشه. خروجی در مرورگر بصورت زیر می باشد:

ارتباط Generator با for..of و Rest

شما میتونین توابع سازنده را فراخوانی کرده تا یک iterator به وجود بیاید و بعد از اون iterator در حلقه for..of یا Rest Operator استفاده کنید. مثلا کد زیر رو در نظر بگیرید:

همونطور که میبینید از همون تابع شمارنده قبل استفاده کردیم و اون رو درون حلقه for..of قرار دادیم و فراخوانی کردیم. با اینکار خروجی زیر نمایش داده میشه:

همچنین میتونین این تابع شمارنده رو با Rest نیز به کار ببرید. بصورت زیر:

میبینید که تابع رو فراخوانی کرده و با استفاده از Rest Parameter اعضای اون رو درون یک آرایه قرار دادیم. خروجی در Console بصورت زیر خواهد بود:

استفاده از Generator با Destructuring

شما میتونین اعضای خاصی رو با استفاده از Destructuring از Generator خارج کرده و درون متغیر مورد نظرتون ذخیره کنید. برای اینکار بصورت زیر عمل میکنیم:

میبینید که مقدار اولیه برگشتی از iterator رو درون متغیر first و بعد از اون دو عدد کاما قرار دادیم و به معنای اینه که کاری به مقدار دوم برگشتی از iterator نداریم. در نهایت مقدار سوم برگشتی از iterator رو درون متغیر three ذخیره کردیم. با اینکار خروجی بصورت زیر خواهد بود:

به همین راحتی.

ترکیب کردن سازنده ها

شما میتونین با استفاده از yield * سازنده ها رو با یکدیگر ترکیب کنید و همزمان از اونا یک iterator بسازید. کد زیر رو در نظر بگیرید:

میبینید که دو تابع سازنده letterMaker و countMaker رو به وجود آوردیم و هر کدام به تنهایی سه عضو رو برگشت میدن. در خط 13 یک تابع سازنده دیگر بنام combine به وجود آوردیم و با استفاده از yield* دو سازنده دیگه رو در اون اجرا کردیم. با اینکار زمانی که در خط آخر تابع سازنده combine رو فراخوانی میکنیم و اون رو در آرایه قرار میدیم، خروجی بصورت زیر میشه:

به همین راحتی. میبینید که خروجی هر دو iterator در پشت سر هم قرار گرفته است و با هم ترکیب شده اند.

ارسال پارامتر به iterator

همونطور که میدونین با استفاده از yield یک مقدار از تابع به سمت بیرون برگشت میدیم و تابع رو متوقف یا pause میکنیم. شما میتونین با استفاده از متد next تابع رو مجددا اجرا کرده و همچنین یک مقدار یا پارامتر رو به درون تابع ارسال کنید (برعکس عملکرد yield). این مقداری که با استفاده از متد next فرستاده میشه، برابر با عبارت yield قبلی که باعث متوقف شدن تابع شده است قرار میگیره. کد زیر رو در نظر بگیرید:

میبینید که یک تابع سازنده بنام hello به وجود آوردیم و دو yield در اون وجود دارد. در خط 6 یک iterator از اون ساختیم. در خط 8 تا آخر نیز با استفاده از متد next اون رو اجرا کردیم.

خب در کد بالا ابتدا در خط 8 متد next فراخوانی میشه و باعث میشه که iterator شروع بشه. کدهای درون تابع سازنده تا جایی که به اولین yield برسند، اجرا شده و تابع متوقف می شود و مقدار Hi برگشت داده میشه. پس تا اینجا {value: "Hi", done: false} در خروجی نمایش داده میشه.

بعد از اون یکبار دیگه در خط 9 متد next استفاده میشه و این بار رشته Mohammad به عنوان پارامتر ارسال میشه و برابر با yield ای که تابع رو متوقف کرده است، قرار میگیره. پس متغیر name برابر با رشته Mohammad میشه و در خط بعد این رشته رو با استفاده از yield دوباره برگشت میدیم و این بار خروجی {value: "Hello Mohammad", done: false} رو مشاهده خواهیم کرد و دوباره تابع متوقف خواهد شد. اگر یکبار دیگه از next استفاده کنیم، چون دیگه هیچ yield وجود ندارد، {value: undefined, done: true} در Console چاپ میشه. پس Console در کل بصورت زیر خواهد شد:

به همین راحتی. برای مطالعه بیشتر میتونین لینکهای زیر رو ببینید:

موفق و پیروز باشید.

یا علی

comment دیدگاه کاربران
Hosein

ممنون آقای اسفندیاری
فقط سوالی که تو این قسمت و سه قسمت قبل برای من پیش اومده اینه که این iterator و generator به چه دردی دقیقا میخوره کجاها میشه ازشون استفاده کردن؟ فکر میکنم استفاده خیلی محدودی داشته باشن.

محمد اسفندیاری

خواهش میکنم دوست عزیز
با سر کار اومدن ES6 خیلی امکانات جدید مانند Set و Map و … اضافه شدن و Symbol.iterator برای بیشتر اونا تعریف شده تا شما به راحتی بتونین به اعضای اونا دسترسی داشته باشید. اینطور میشه گفت که بیشتر چیزها بر پایه همین iterator ها هستند. بخاطر همین هست که حلقه for..of و Rest Parameter و … اضافه شدن تا به راحتی بتونین به اعضای Iterator ها دسترسی داشته باشید.
https://appendto.com/2016/06/powering-javascript-with-generators/
Iterator و Generator در اکثر زبانهای دیگه مانند Python نیز وجود دارد و نیاز به اونا در Javascript هم وجود داشت. امکانات جدید و خاصی رو به برنامه نویسان میدن که کارهایی که قبلا نمیشد انجام داد رو به راحتی انجام میدن. مثلا همین که بتونیم یک تابع رو در یک جا متوقف کنیم و کارهای مورد نظرمون رو انجام بدیم و دوباره اون رو اجرا کنیم، در بعضی از مواقع خیلی کارمون رو راه میندازه.
اما همونطور که خودتون هم گفتید شاید خیلی از اونا در پروژه های خودمون استفاده نکنیم و از این موارد بیشتر کسانی استفاده میکنن که میخوان یک Library یا Framework رو به وجود بیارن.
از Generator برای برنامه نویسی Asyncronous استفاده میشه و کارها رو راحت تر میکنه. لینکهای زیر رو ببینید:
http://2ality.com/2015/03/no-promises.html
https://medium.com/javascript-scene/the-hidden-power-of-es6-generators-observable-async-flow-control-cfa4c7f31435
موفق باشید

ارسال نظرات

کاربر گرامی، امکان ارسال نظر و پشتیبانی برای دوره های مجازی فقط برای دانشجویان این دوره امکان پذیر می باشد.