<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Hassan Gilak</title>
        <link>https://virgool.io/feed/@hasangilak</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-25 11:56:23</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/56/avatar/cRUnIT.png?height=120&amp;width=120</url>
            <title>Hassan Gilak</title>
            <link>https://virgool.io/@hasangilak</link>
        </image>

                    <item>
                <title>مهاجرت - فرار بزرگ</title>
                <link>https://virgool.io/@hasangilak/emigration-the-great-escape-l1vk2gyegns6</link>
                <description>‌Berlin Gateواقعا چیزی که مشخصه و با تمام وجودم درکش کردم, برای من مهاجرت ترک ساده وطن (هتل) نبود. من مثل خیلی های دیگه از یه جایی از نوجوونیم شروع کردم به کلنجار رفتن با محیط دورم و زیر بار نرفتن هر چیزی که میخواست بهم قالب و چارچوبی رو بقبولونه. از مدرسه اخراج شدن. سه ترم مشروطی دانشگاه و انصراف از دانشگاه. روابط عاطفی که تمام قلب و روانم رو منفعل کرده بود. خانواده ای که روی دوش اون ها ایستادم ولی کلی دل شکستگی و جنگ سرد بینمون هست. من چیزی رو که برای بقیه شاید درست کار میکنه رو نمیتونستم برای خودم قبول کنم. و با اصل خیلی چیز ها مشکل ندارم. خیلی از هم دوره ای های من توی بهترین دانشگاه های دنیا الان دارن دکتری میخونن و من از کل سیستم آموزشی ایران یه فوق دیپلم دارم. مهارت های مهمی تو زندگی هست ولی تو این ۲۶ سال از زندگیم, کله شق بودن بهترین کمک هارو بهم کرده. من آدم باهوشی نیستم. حافظه جالبی هم ندارم. ولی به چیزی که علاقه دارم اهمیت خیلی جدی میدم. تو راهم مسخره شدم. کم اهمیت جلوه داده شدم. افسرده شدم. خود خوری کردم ولی یه چیزی دوباره بهم اجازه داد که ادامه بدم و بهتر و بیشتر یاد بگیرم. همه ی این تمسخر ها و بلند شدن ها با من کاری کرده که اگر به طرز احمقانه ای تو چیزی اشتباه کنم و کسی با تمسخر تمام بهم مشکلم رو بگه حتی ذره ای ناراحت نمیشم و خوشحالم که میدونم اشتباه کردم و باید درستش کنم. من یک بار از بابلسر به تهران مهاجرت کردم. تلاشمو کردم که تو مازندران کار بکنم و پیشرفت کنم. ولی از هر کاری به کار دیگه ای که میرفتم هیچ درامدی برام نداشت. همین جوری سر خورده تر و افسرده تر به کار بعدیم میرفتم و شکست های بد تری میخوردم. چه از لحاظ فنی و کاری چه از لحاظ روحی. برای من اون روز ها تلخ ترین سرمایه گذاری ها روی خودم بود. روزایی که کلاس های فشرده آیلتس رو با استاد عزیزم رضا خرمیان میگذروندم. روزایی که بین فواصل شهری همش داشتم تو تبلت چیز جدید یاد میگرفتم. شبایی که به خودم قول میدادم تا این مشکل درست نشه نمیخوابی یا تا این چیزو نفهمی به تحقیقت ادامه میدی. کتاب هایی که واقعا درکش برام سخت بود و برای فهمیدن یه جملش مجبور بودم کلی سرچ کنم تا از ذهن آدم های دیگه و نوشته اون ها به قضیه نگاه کنم تا شاید متوجه بشم منظور نویسنده کتاب چی بوده. روزایی که با انرژی کار میکردم و استرس بعد از آب بیشترین جز تشکیل دهنده بدن من بود. افسردگی و اضطراب با دانش و مهارت کم من در ارتباط با آدم های دورم از من تصویر خیلی بدی ساخت. هنوزم که هنوزه مهارت کافی برای ایجاد ارتباط بین آدم های دورم رو ندارم ولی خب دوست دارم تغییر کنم. ولی هر وقت از من میپرسن که چرا از ایران اومدی دوست دارم بگم بخاطر پیدا کردن آرامش. یک سال آخری که تهران بودم درامد خیلی خوبی پیدا کرده بودم که فکر نمیکنم اینجا هیچ وقت به اون رقم برسم با کارمندی. ریموت کار میکردم و یا پروژه ای. ولی آرامش مالی خیلی کوچیکتر از آرامش درونی هست. من یه آدم خسته از اجتماع دورم با هزار یک مشکل دستو پنجه نرم میکردم که هیچ مهارتی هم در مقابل مشکلات اجتماعیم نداشتم. ناشیانه ترین برخورد ها رو میکردم و صدمات روحی مالی زیادی داشتم.مهاجرت از بابلسر به تهران و از تهران به برلین برای من که تو هر دو تا کیس متاهل بودم خیلی سخت بود. ولی بیشترین سختی رو همسر عزیزم کشیده. دوری های طولانی و خانواده هایی که هیچ چیز از ما رو قبول ندارن و همچنان ما هستیم و زندگی دو گانه یکی در شهری که هستیم و یکی در شهر خانواده هامون. برای من آرامش یعنی رسیدن به اون چیزی که ندای درونت بهت میگه. چیزی که زهرای من و همین طور من خیلی وقته سرکوبش کردیم. اگر من رو بشناسید همیشه شبیه بچه های ۱۴ ساله هستم که دوست نداره شبیه آدم های بالغ باشه. ولی سرخوردگی ها و‌ آسیب های زیادی هم داشتم از این طرز برخوردم برای دیگران و خودم. از این پاراگراف های تلخ و نچندان پراکنده ی من ذهن آشفته و روح کدرم رو میبینید. بزارید یه سیگار بکشم میام. دلمردگی رفقا. درد من دل مردگیه. تاریکی و بی هدف شدن. نمیدونی به کدوم سمت بری تا خوش حال تر باشی. تشنگی برای خوشحالی. و باز هم میشنوی از دوروبریات که تو فرار کردی به جلو به جای حل مسئله. باشه بابا. منم همیشه میگم از ایران فرار کردم. شاید سال پیش بود که نزدیک ترین حالت ممکن رو به مهاجرت به استکهلم پیدا کرده بودم. هفته ها مطالعه الگوریتم ها و سوال های مصاحبه و کتاب های فنی و قبول شدن مصاحبه. منتظر موندن برای ویزا و رد شدن و پژمرده شدن عزیزترین آدم زندگیم. زهرای من جلوی چشمام آب شد. منم مونده بودمو آوارگی با سنگینی غم همسرم. شروع کردم به فرستادن رزومه. شاید ۵۰۰ تا رزومه فرستادم و ۵۰۰ بار رد شدم. تو همین مدت یکی از دوستانم بهم راهی رو پیشنهاد داد که قبلا هم شنیده بودمش ولی این دفعه جدی گرفتمو به ویزای آلمان ختم شد. ریکروتر recruiter ها آدم هایی هستن که برای شما کار پیدا میکنن و از شما حق ندارن پولی بگیرن. بعد از این که شما با شرکت قرار داد بستید از شرکت پولی خوبی میگیرن. هرچی حقوق شما بیشتر باشه سود اون ها بیشتر هست. ولی خب با هر دوز و کلکلی هم که شده دوست دارن از شما پول در بیارن پس سعی میکنن تا حدی که شده همه فرایند رو خوشایند جلوه بدن به هر دو طرف قضیه. شمایی که دنبال کار هستید و شرکتی که دنبال نیرو هست.من خیلی خوش شانس بودم و هم تا خرخره توی دردسر. دو روز قبل از پروازم به برلین از شرکتی که باهاش کار میکردم و اسپانسر ویزام شده بود اخراج شدم ولی بهم گفتن بیا و ادامه بده و دنبال کار باش. قبل پرواز با دوستام خدافظی کردم. همشونو بغل کردمو ازشون خواستم هوای زهراو داشته باشن. روز اولی که به برلین رسیدم فرود اومد دنبال فرودگاه و رفتیم خونش. الی بهم کارت مترو و تردد شهری رو داد که سه ماهی ازش استفاده کردم. البته هنوز تشکر خیلی به جایی از این لطفی که بهم داشتن نکردم و منتظرم به وقتش یه تشکر کنم که حد اقل بتونم تو چشمشون راحت تر نگاه کنم. شبش رفتم خونه ی احسان و دو ماهی اجازه داد پیشش باشم تا یه کاری پیدا کنم. تمام تلاشم رو هم بکنم از پس لطف احسان بر نمیام. این آدم ها منجی من بودن تو بدترین روز های مهاجرت و هرجور تشکر کنم چیزی از لطف و بزرگی اونها رو جبران نمیکنه. اون روز ها شاید ۲۰۰ ۳۰۰ یورو سیگار کشیدم. ( خانواده عزیزم که این مطلب رو میخونید. من یک ساله سیگار میکشم. اون مبل تو خونم رو هم من سوزوندم نه رفیقام )به طور مکرر مصاحبه ها رو تو برلین رد میشدم تا وقتی که رفتم سراغ شرکت lendis.io. سی تی اوشون بعد از رد کردن من پنج دقیقه باهام صحبت کرد و من هم سعی کرده بودم از همه رد شدن ها درسی بگیرم. از اون روز به بعد مصاحبه هام خیلی خوب پیش میرفت و داشتم به قرار داد نزدیک میشدم. نهایت با شرکت zizoo.com به نتیجه رسیدم و این بزرگترین خوش شانسی من بود بعد از گرفتن ویزای آلمان. شرکتی که مالتی نشنال هست و آدم های خونگرم زیادی اونجا دورمن. ازم راضین و من هم همه تلاشم رو دارم میکنم که تصویر خوبی داشته باشن ازم. الان که این مطلب رو مینویسم اجازه کار گرفتم در آلمان و حساب بانکی دارم. سیستم بروکراسی اداری آلمان کند پیش میره و همه چی منوط به داشتن یک خونه یا یک اتاق هست. با اجاره اتاق و ثبت آدرسم تو اداره ی آلمانی تازه تونستم وقت برای اجازه کار و باز کردن حساب بانکی بگیرم. بعد از استخدام در zizoo سعی کردم یکم خوشحال تر باشم. یه سفر به هلند رفتم. دریاچه های دورو بر برلین رو دیدم و الان هم منتظر اولین میت آپ ری اکت رو تو برلین شرکت کنم. منتظرم همسرم بره برای مصاحبه سفارت در این هفته و خونمون رو در تهران تحویل بده و بیاد پیشم. تنهایی برای من که این همه دلمردم اینجا خیلی سخت میگذره. گریه های همسرم برام خیلی گرون تموم میشه. باید بیاد و یک دل سیر خودمون باشیم و خوش بگذرونیمو به چشماش زل بزنم. دریاچه شیطان - برلینآمستردامدر ضمن. من دیگه هیچ وقت دوست ندارم برای زندگی به کشتارگاهی برگردم که هواپیمای اوکراینی رو با موشک نظامی به خون کشید و سه روز تمام در موردش دروغ گفت. اینجا بین ایرانی هایی هستم که برای من مهربانی بی حدو اندازه ای داشتن. اشک میریزمو مینویسم. مادرم. پدرم. شما من رو به اینجا رسوندین. با همه دعوا ها و فریاد ها گریه هایی که کردیم. من روی شونه های شما ایستادم. و زهرای من. کسی که تو همه ی سختی ها و شادی باهام بودی. دوستت دارم و منتظرم بیای و همه چیز رو از نوع شروع کنیم.این آهنگ هم دلیل بغض شکسته این روز های منهhttps://open.spotify.com/track/1HVSEcBlRVV12yVx9F2SiLگنجشککای بی نام و نشونپرنده های بی همزبونبهتره دیگه برید خونتوندردتون نخورد به دردمونکم زدنتون بستنتون ها ؟کم توو قفس کردنتون باز ؟اومدین اینجا واسه پروازکم نکرده کردن گردنتون ؟ازینجا مثل غریبه برینازین شهر واسه همیشه برینبرین دنبال یه شهر بهترشاید به امید یه نتیجه بریناز سرتون زخم ِ بدنتونغمتون نوکتون جیک جیک صبحتونترس تو شبتون و حبس نفستوننفسم گرفتبرین یه جایی که ترسی ندارهواسه پرواز مرزی ندارکلاغ ولگردی ندارههیچ غمی و ترسی ندارهیه جایی که همه منظره ها خوبنآدما وقتی وا میشن پنجره ها خوبنکور و نگاه خوبن، لال و صدا خوبنشاپرکا خوبن، شاه و گدا خوبنبریم یه جا که ته قصه بی کویرهدور از سینه های آزاد که دشنه میدریدشیه چند صباحی بو تشنگی نگیرهمیشه بریم یه جا زندگی نمیرهنه کار ما نیآسمون دولت پرواز بال ما نینشونی ما همون خنده های مُرده سچیزی جز این فریاد نام ما نیبرین اما نمیخواداین سفر کدوم و کجا نمیخوادتوو این سرما دستام چه تنهاناگه توو ترسی ازت ها نمیخوادبرین اما نمیخواداین سفر کدوم و کجا نمیخوادتوو این سرما دستام چه تنهاناگه توو ترسی ازت ها نمیخوادمن که دیگه پیرم از این حرفا سیرمیه جورایی گیرم شما برین میرمبرین برین این قفس رو بشکونینبرین سلام منو به نفس برسونینشاید یه روز جای شبیهم رو داشتینیه جایی با هم قرار پریدن گذاشتیماین خطا که میگن مرزن ندیدینبدون هیچ التماسی ارزن خریدینتلخ نشینین انقد سخت نگیرینرو سیم برق نشینینکوچیکین ظریفین میمیرینهرچقد عزیزین غریبینمیبینین سختهاین نفس تنگتر از خودِ تنگهاین نفس ننگ تر از خود ننگهوقتی یه لحظه حسی توو وجود تو نیست که بخندهسختهشاید یه روزی همتون مامان داشتینکلی مهر با وجود آذر یه آبان داشتیندرد ندیدین و دردی دردتون نشدسردتون نشد به دستتون نخورد تیرپاتونم نکرد گیرشاید آزادی رو فقط نگفتینشاید دیدینیش حسش کردینانجامش دادین بدون هیچ ترسیگنجشککای بی نام و نشونپرنده های بی همزبونمنم نام و نشونتونمنم همزبونتوندرسته باهمدیگه یه کمی فرقو داشتیمخسته بودیم کوفته بودیم ولی صبرو داشتیمشاید یه روز جای شبهیم رو داشتیمیه جا باهم قرار پریدن گذاشتیمدور از اونجا که رویا یه مُرده سپرواز توو تسخیر خفاش لنکتهدور از خیال جریان توو رودهای آزادتوو اونجا که دریا یه مُرداب گنده سکل زندگی رو انشاء کنیم به دردهم هنو نمُرده املاء کنیم که هستآسمون یعنی رقص فوجی از مابا پروازمون امضاء کنیم شکستبرین اما نمیخواداین سفر کدوم و کجا نمیخوادتوو این سرما دستام چه تنهاناگه توو ترسی ازت ها نمیخوادبرین اما نمیخواداین سفر کدوم و کجا نمیخوادتوو این سرما دستام چه تنهاناگه توو ترسی ازت ها نمیخواداین قفس ننگ تر از خوده ننگهشاید قسمت های بعدی رو هم بنویسم در مورد جزیات آلمان و تخصصی تر در مورد رزومه نوشتن و کار پیدا کردن ولی فعلا وقتی نیست برای من و کم تجربم در برلین. ممنون که خوندین و وقت گذاشتید. </description>
                <category>Hassan Gilak</category>
                <author>Hassan Gilak</author>
                <pubDate>Sat, 11 Jan 2020 15:50:28 +0330</pubDate>
            </item>
                    <item>
                <title>جاوااسکریپت چجوری کار می‌کنه؟ ایونت لوپ و قدرت گرفتن برنامه‌نویسی async و ۵ روش برای بهتر کد نوشتن به کمک async/await - قسمت اول</title>
                <link>https://virgool.io/JavaScript8/async-programming-under-the-hood-event-loop-part-1-hfr5zzmikjgy</link>
                <description>سری &quot;جاوااسکریپت چجوری کار می‌کنه؟&quot; بازگردان مقاله‌های Alexander Zlatkov به زبون خودم هست. هدف از این کار در مرحله‌ی اول یادگیری خودم و انتشار این مقاله به فارسیه.قرارم بر این نیست که همه‌ی کلمه‌ها رو به فارسی بگم، به این دلیل که اگر خواستید بیشتر در مورد کلمات کلیدیش جستجو داشته باشید، بتونید راحت‌تر این کار رو انجام بدین.اهمیت این نوشته برای من محتواش هست نه طرز بیان یا نگارشش. ممنون می‌شم اگر در محتوا یا در طرز بیان یا نگارش اشکالی هست بیان کنید تا بتونم بهترش کنم.بازگردانی شده از: How JavaScript works: Event loop and the rise of Async programming + 5 ways to better coding with async/awaitاین بار با مروری بر مشکلات برنامه‌نویسی روی محیطی تک تردی و معرفی راه حل‌های این مشکل برای ساخت یک UI خفن؛ گفته‌های خودمون رو در نوشته‌ی اول این سری تکمیل می‌کنیم و در آخر هم طبق رسم همیشگی ۵ نکته در مورد تمیزتر کد زدن به کمک async/await می‌گیم.چرا تک تردی بودن محدودیت به حساب میاد؟تو اولین نوشته رو این سؤال فکر کردیم که چه اتفافی می‌اوفته وقتی تابعی در call stack، زمان زیادی برای اجرا بخواد؟ مثلا اجرای یه الگوریتم سنگین پردازش عکس تو مرورگر.هر زمانی که call stack تابعی رو در حال اجرا داشته باشه مرورگر هیچ کار دیگه‌ای نمی‌تونه انجام بده و بلاک شده. این به این معنی هست که نمی‌تونه صفحات رو رندر کنه یا کد دیگه‌ای رو اجرا کنه و به طور کامل گیر کرده و اینجاست که مشکل خودش رو نشون می‌ده. اپلیکیشن ما دیگه UI بهینه و جذابی نداره.شاید تو بعضی از کیس‌ها چیز مورد داری نباشه ولی ما یه مشکل بزرگ‌تر دیگه‌ای داریم. وقتی مرورگر ما شروع به اجرای کلی کار زیاد از call stack می‌کنه، باعث می‌شه مرورگر مدت زیادی نسبت به امور موازی با جاوااسکریپت واکنش نشون نده. (رندرینگ UI و اجرای جاوااسکریپت روی یک ترد انجام می‌شه). تو این حالت اکثر مرورگرها اروری نمایش می‌دن که حاوی این درخواست از کاربر هست که این صفحه رو ببندن یا نگه دارن. فاجعست. هم زشته هم کل UX رو بهم ریخته.اجزای سازنده ی جاوا اسکریپتممکنه شما اپلیکیشن جاوااسکریپت‌تون رو توی یه فایل .js بنویسید ولی قطعاًً همون برنامه هم از قسمت‌های مختلفی تشکیل شده که هر کدوم‌شون زمان اجرای مختلفی دارن و فقط یه کدوم از اون‌ها در لحظه در حال اجرا هست و بقیه بعداً اجرا می‌شن. رایج‌ترین اجزای سازنده‌ی برنامه‌های ما توابع هستن.مشکل اکثر دولوپرهایی که تازه با جاوااسکریپت آشنا شدن در درک ترتیب اجرای برنامه هست. گاهی ممکنه کدی که در لاین یک نوشتیم بعد از اتمام همه‌ی لاین‌ها اجرا بشه. در حقیقت کدهایی که الان در حال اجرا هستند ولی اتمام اجرای اونها برای الان نیست رو تسک‌های اسینکرنس (asynchronous) می‌گن که این سبک دستورهای اجرایی، مشکلی که در بالا بهش اشاره کردیم رو ندارن (بلاک کردن کل مرورگر ).به تکه کد پایین نگاه کنید:// ajax(..) is some arbitrary Ajax function given by a library
var response = ajax(&#039;https://example.com/api&#039;);

console.log(response);
// `response` won&#039;t have the responseخب احتمالاًً می‌دونید یک درخواست ایجکس استاندارد، سینکرنسلی (synchronously) اجرا نمی‌شه و خب طبق این گفته تابع ajax جواب مورد نظر مارو return نمی‌کنه تا متغیر response اختصاص داده بشه.ساده‌ترین راه برای صبر کردن برای جواب یک تابع اسنیکرنس استفاده از کالبک‌ها هست.ajax(&#039;https://example.com/api&#039;, function(response) {
    console.log(response); // `response` is now available
});در حد یک نکته‌ی کوچیک: البته ما می‌تونیم درخواست‌های ایجکس سینکرنس بسازیم. هیچ‌وقت این کار رو نکنید. اگر همچین کاری کنیم UI رو به طور کامل بلاک کردین و کاربر نمی‌تونه جایی کلیک کنه، اسکرول کنه، دیتا وارد کنه و یا به صفحه‌ی دیگه‌ای جابجا بشه.به طور کلی تراکنش کاربر با مرورگر رو مختل می‌کنه و کار توصیه شده و درستی نیست.با این یه تیکه کد می‌تونید درخواست سینکرنس درست کنید که استفاده از این کد توصیه نمی‌شه.// This is assuming that you&#039;re using jQuery
jQuery.ajax({
    url: &#039;https://api.example.com/endpoint&#039;,
    success: function(response) {
        // This is your callback.
    },
    async: false // And this is a terrible idea
});ما فقط از درخواست ایجکس به عنوان یه مثال صحبت کردیم ولی می‌شه همه‌ی کدها رو به طور اسینکرنس اجرا کرد، اون هم به کمک تابع setTimeout. کاری که این تابع انجام می‌ده یک رویداد رو ایجاد می‌کنه که در چند لحظه‌ی بعدی قرار هست اجرا بشه. به این تکه کد نگاه کنید:function first() {
    console.log(&#039;first&#039;);
}
function second() {
    console.log(&#039;second&#039;);
}
function third() {
    console.log(&#039;third&#039;);
}
first();
setTimeout(second, 1000); // Invoke `second` after 1000ms
third();خروجی این کد این شکلیه first
third
secondکالبد شکافی Event loop بذارید این مبحث رو با یه ادعای عجیب شروع کنیم. تا قبل از ES6 خود زبان جاوااسکریپت مفهومی اسینکرنس بودن رو &quot;به طور مستقیم&quot; در خودش نداشته هر چند که امکان اجرای کدهای اسینکرنس رو به کمک setTimeout داشت. موتور اجرایی جاوااسکریپت در حقیقت فقط وظیفه‌ای جز اجرای یه مشت دستور که در هر زمان بهش داده می‌شه رو داره.برای اطلاع بیشتر از نحوه‌ی کار کردن موتور V8 به پست قبلی ما مراجعه کنید.خب پس چه چیزی به موتور اجرایی جاوااسکریپت دستور انجام برنامه‌های شما رو می‌ده؟ در واقع موتور جاوا اسکپریت به طور ایزوله اجرا نمی‌شه و توسط یه میزبان مورد استفاده قرار می‌گیره، که این میزبان‌ها در چشم ما دولوپرها بیشتر مرورگرها و Nodejs هستن. ولی خب الان جاوااسکریپت همه جا سرک کشیده. از روبات‌ها و یا چراغ‌ها که هر کدوم این‌ها یک میزبان متفاوت برای موتور جاوااسکریپت به حساب میان.نقطه‌ی مشترک همه‌ی این میزبان‌ها یک مکانیزمی هست به نام event loop، که کارش هندل کردن اجرای کدهای جاوااسکریپتی هست که با هر بار فراخوان کردن موتور جاوااسکریپت این کار صورت می‌گیره.این به این معنی هست که موتور جاوااسکریپت یه محیط اجرایی کد هست که در هر لحظه می‌شه کدهای جورواجور جاوااسکریپت رو بهش داد تا اون‌ها رو اجرا کنه و این میزبان هست که ایونت‌ها و جریان اجرای کدها رو در کنترل خودش داره.برای مثال وقتی کد شما درخواست ایجکسی رو برای دریافت اطلاعات به سمت سرور می‌فرسته شما در قالب یه تابع کالبک منتظر جواب از سمت سرور می‌مونید. در همین لحظه موتور اجرایی به میزبان میگه من دیگه فعلاًً کارها رو متوقف می‌کنم. هر وقت جواب رو از سرور گرفتی این تابع کالبکی رو که مشخص کردم برات فراخوانی کن.مرورگر به عنوان میزبان یه لیسنر ایجاد می‌کنه برای دریافت جواب از نتورک، و هر وقت که جوابی رو دریافت کنه از سمت نتورک، تابع کالبکی رو که نوشته بودیم برای اجرا به event loop برمی‌گردونه.به دیاگرام زیر دقت کنید:می‌تونید در مورد memory leak و call stack در مقاله‌ی قبلی بیشتر بخونید.تو دیاگرام یه قسمتی هست با عنوان Web APIs. در واقع این‌ها تردهایی هستن که بهشون دسترسی مستقیم نداریم ولی می‌تونیم اون‌ها رو صدا بزنیم. اون‌ها قسمتی از مرورگر هستن که کنکارنسی رو فراهم می‌کنن. و اگر شما هم Node.js دولوپر باشید و میزبان رو نودجی‌اس در نظر بگیریم این ها apiهایی هستن که توسط زبان c++ فراهم شدن.خب بریم سراغ اصل مطلب. event loop چی هست؟ایونت لوپ فقط یه کار ساده داره. اونم مانیتور کردن call stack و callback queue. اینجوری کار می‌کنه که هر وقت call stack رو خالی ببینیه از صف کالبک‌ها یه دونه برمی‌داره و به call stack اضافه می‌کنه و در جا اجراش می‌کنه.در event loop به هر بار تکرار این اتفاق یه tick گفته می‌شه و هر آیتم درون صف یک event نام داره که در حقیقت یه تابع callback هست.console.log(&#039;Hi&#039;);
setTimeout(function cb1() { 
 console.log(&#039;cb1&#039;);
 }, 5000);
console.log(&#039;Bye&#039;);بیاید این کد رو اجرا کنیم و بررسی کنیم چه اتفاقاتی داره می‌اوفته:۱- وضعیت مشخصه. call stack خالیه. console مرورگر هم خالیه.۲- کال استک با اولین خط پر شدهconsole.log(&#039;Hi&#039;)۳- خط اول اجرا شد۴- خط اول از call stack حذف شد.5- خطی که شامل setTimeout هست وارد callstack میشه۶- خب setTimeout اجرا میشه و مرورگر یه تایمری رو که قسمتی از web api هست برای ما راه میندازه. این تایمر قرار شمارش معکوس تا اجرای اون کالبکی که به setTImeout دادیم رو هندل کنه.۷- خود setTimeout کارش تموم شده و باید از call stack حذف بشه.۸ - خطر آخر به call stack اضافه شدهconsole.log(&#039;Bye&#039;)۹- خط آخر اجرا شد۱۰ - خب بعد از اجرا هم باید از callstack حذف بشه11- بعد از حداقل ۵۰۰۰ میلی ثانیه تایمر کارش تموم میشه و خود تایمر تابع کالبک setTimeout رو به call stack منتقل میکنه.۱۲- حالا نوبت cb1 هست. event loop این تابع کالبک رو از صف کالبک ها خارج میکنه و به call stack منتقل میکنه.۱۳- تابع cb1 اجرا میشه و در ادامش اخرین دستور کنسول هم به call stack اضافه میشه.۱۴- این دستور اجرا میشهconsole.log(&#039;cb1&#039;)۱۵- تابع log از call stack حذف میشه۱۶- حالا نوبت cb1 هست که از call stack حذف بشهیه نگاه سریع به همه این ۱۶ تا اتفاقجالبه بدونید داستان تو ES6 تغییر کرده به این صورت که موتور جاوااسکریپت هست که مشخص می‌کنه event loop باید چجوری کار کنه و ازش استفاده بشه. این یه جورایی داره میگه event loop تنها و تنها جزو وظایف میزبان (‌مروگر، Node.js) به حساب نمیاد و یه قسمتی از اون سمت جاوااسکریپت سوق داده شده. یکی از مهم‌ترین دلایل این تغییر معرفی Promise هاست. برای این قابلیت نیاز به کنترل همه جانبه‌ی event loop یک ضرورت به حساب میاد. در مورد این موضوع بیشتر توضیح خواهیم داد.تابع setTimeout چه جوری کار میکنه؟نکته‌ی مهم در مورد setTimeout اینه که به صورت اتوماتیک تابع کالبک ما رو وارد صف event loop نمی‌کنه. یه تایمر درست می‌شه و هر وقت که تایمر منقضی بشه میزبان تابع کالبک ما رو تازه وارد صف می‌کنه و تابع باید صبر کنه تا فرآیند tick اتفاق بیافته تا از صف event loop به call stack منتقل بشه.setTimeout(myCallback, 1000);معنی کد بالا این نیست که myCallback دقیقاً بعد از ۱۰۰۰ میلی‌ثانیه اجرا می‌شه. در حقیقت بعد از این مدت myCallback تازه به صف event loop اضافه می‌شه. و خب تازه آخر داستان نیست. اگر تو صف event loop توابع دیگه زودتر تو صف وارد شده باشن اجرای تابع myCallback بیشتر به تعویق می‌افته.الان که می‌دونیم event loop چیه و setTimeout چجوری کار می‌کنه استفاده از setTimeout با زمان ۰ میلی ثانیه به عنوان پارامتر دوم به این معنی می‌شه که callback که به عنوان پارامتر اول پاس دادیم بعد از خالی شدن call stack اجرا می‌شهsetTimeout(callback, 0)به کد زیر نگاه کنید:console.log(&#039;Hi&#039;);
setTimeout(function() { 
    console.log(&#039;callback&#039;);
}, 0);
console.log(&#039;Bye&#039;);با وجود این که زمان رو روی ۰ میلی‌ثانیه تنظیم کردیم ولی خروجی مرورگر جور دیگه‌ای هستHi
Bye
callback المان جدیدی به نام Job و Job Queue در جاوا اسکریپتمفهوم جدیدی به نام Job Queue در ES6 معرفی شده که یک لایه بالای event loop هست که احتمالاً وقتی با Promiseها کار می‌کردین بهش برخوردین.فعلاًً در مورد این قضیه یکم صحبت می‌کنیم تا بتونیم وقتی در مورد برنامه‌نویسی اسینک با پرامیس بحث می‌کنیم متوجه نحوه‌ی مدیریت و اجرای اون‌ها بشیم.اینجوری تصورش کنید که صف Jobها به انتهای هر tick از صف event loop متصل هست. بعضی از اکشن‌های اسینک در زمان انجام tick باعث ایجاد یه ایونت جدید نمی‌شن و به جای اون یک آیتم جدید Job به انتهای Job queue اضافه می‌شه.این به این معنی هست که ما می‌تونیم کدهامون رو بعدا اجرا کنیم و مطمئن باشیم قبل از هر چیز دیگه‌ای اجرا می‌شن.به مثال زیر دقت کنید.var promise = new Promise(function(resolve, reject) {resolve(1)});promise.then(function(resolve) {console.log(1)});
console.log(&#039;a&#039;);
promise.then(function(resolve) {console.log(2);});
setTimeout(function() {console.log(&#039;h&#039;)}, 0);
promise.then(function(resolve) {console.log(3)});
console.log(&#039;b&#039;);

// a
// b
// 1
// 2
// 3
// hاول کدهای سینک اجراشون تموم می‌شه و نوبت تیک event loop میرسه. سه تا Job با استفاده از Promise.then ها به Job queue اضافه شده که به صورت FIFO به call stack اضافه و اجرا می‌شن. و بعد از خالی شدن صف Job queue نوبت اجرای تیک هست و برداشتن تابع کالبک setTimeout از صف event loop به call stack. (به Job‌هایی که توسط promise.then اضافه می‌شن PromiseJob می‌گن. چند نوع Job دیگه هم وجود داره که می‌تونید سرچ کنید و در موردش بخونید: enqueue job، script job، TopLevelModuleEvaluationJob )هر Job میتونه Job‌های دیگه‌ای رو به انتهای همین صف در حال اجرای Job queue اضافه کنه. تئوریک می‌تونیم با این قابلیت یه لوپ بی‌نهایت درست کنیم. یه جابی باشه که هی جاب اضافه کنه به انتهای صف در حال اجرا. یه چیزی مشابه while true.جاب ها مشابه setTimeout با پارامتر دوم 0 هست ولی گارانتی می‌کنه حتماً بعد از خالی شدن کال استک اولین چیزی باشه که اجرا می‌شه.کالبک هاهمون‌طور که می‌دونید کالبک‌ها رایج‌ترین روش برای مدیریت فرآیند اسینکرنس و یه پترن خیلی مهم و اساسی توی جاوااسکریپت به حساب میان. خیلی از اپلیکیشن‌های ساده و پیچیده بر مبنای همین کالبک‌ها ساخته شدن.قطعاًً میدونیم که کالبک ضعف‌های خودش رو داره و خیلی‌ها تلاش کردن راه‌حل‌های دیگه‌ای برای حل مسأله پیدا کنن. دونستن زیربنای اون راه‌حل‌های جدید، به ما کمک می‌کنه بهتر استفاده کنیم از اون‌ها.کالبک های تو در توبه کد زیر دقت کنید:listen(&#039;click&#039;, function (e) {  
    setTimeout(function() {
       ajax(&#039;https://api.example.com/endpoint&#039;, function (text) {
            if (text == &quot;hello&quot;) { 
                doSomething();	    
            } else if (text == &quot;world&quot;) { 
               doSomethingElse();     
           }
       });    
    }, 500);
 });سه تا تابع تو در تو رو مشاهده می‌کنید که هر کدوم نماینده‌ی یکی از قسمت‌های اسینکرنس در جاوااسکریپت هستند. listener، setTimeout و ajax.به این سبک کد می‌گن callback hell ولی تقریباً می‌شه گفت کالبک هل ربطی به تابع‌های تو در تو نداره و مشکل از جای دیگه‌ای هست که آب میخوره. هروقت دولوپرها به ترتیب اجرای برنامه کدهاشون رو می‌نویسن کالبک هل به وجود میاد. در ادامه می‌خوایم در مورد روش‌هایی صحبت کنیم که ترتیب کدنویسی رو برای ما تغییر می‌دن.پایان قسمت اول</description>
                <category>Hassan Gilak</category>
                <author>Hassan Gilak</author>
                <pubDate>Fri, 22 Mar 2019 21:49:02 +0430</pubDate>
            </item>
                    <item>
                <title>جاوا اسکریپت چه جوری کار میکنه؟ مدیریت حافظه و ۴ روش برای مهار کردن مموری لیک</title>
                <link>https://virgool.io/JavaScript8/how-javascript-works-memory-management-how-to-handle-4-common-memory-leaks-ldxonke9zy3k</link>
                <description>سری &quot;جاوا اسکریپت چه جوری کار میکنه؟&quot; بازگردان مقاله های Alexander Zlatkov به زبون خودم هست. هدف از این کار در مرحله ی اول یادگیری خودم و انتشار این مقاله به فارسیه. قرارم بر این نیست که همه کلمات رو به فارسی بگم, به این دلیل که اگر خواستید بیشتر در مورد کلمات کلیدیش جستو جو داشته باشید, بتونید راحت تر این کارو انجام بدین. اهمیت این نوشته برای من محتواش هست نه طرز بیان یا نگارشش. ممنون میشم اگر در محتوا یا در طرز بیان یا نگارش اشکالی هست بیان کنید تا بتونم بهترش کنم. بازگردانی شده از: How JavaScript works: memory management + how to handle 4 common memory leaksهفته ها پیش, ما یه سری مقالات رو در مورد درک عمقی تر از جاوا اسکریپت و چه جوری کار کردنش  شروع کردیم: ما فکر میکردیم که با دونستن اجزای تشکیل دهنده جاوا اسکریپت و تعاملشون با هم شما میتونید کدها و برنامه های بهتری بنویسید.اولین مطلب این سری تمرکزش روی مرور بر موتور جاوا اسکریپت, run time و call stack بوده. مطلب دوم این سری بررسی اجزای داخلی موتور V8 گوگل و چند تا نکته درباره ی بهتر جاوا اسکریپت کد زدن هست.در سومین پست, در مورد موضوع حیاتی دیگه ای بحث میکنیم به نام memory leak که داره بیشتر و بیشتر توسط برنامه نویس ها فراموش میشه. دلیلش هم  پیچیده شدن و بالغ شدن زبان های برنامه نویسی هست که داریم هر روز ازشون استفاده میکنیم و همین طور به توضیح چند تا نکته در مورد کنترل مموری لیک تو جاوا اسکریپت میپردازیم.بررسی کوتاهزبونی مثل C, به کمک تابع هایی مثل malloc و free امکان مدیریت سطح پایین حافظه رو به دولوپر سپرده. این تابع های سطح پایین و اولیه به توسعه دهنده ها کمک میکنه تا مقداری از حافظه رو از سیستم عامل در اختیار بگیرن یا به سیستم عامل برگردونن. جاوا اسکریپت در زمان ساخت آبجکت ها و استرینگ ها حافظه رو اشغال میکنه و وقتی نیازی به اون ها نباشه حافظه رو آزاد میکنه که به این پروسه گاربج کالکشن میگیم. این فرایند به ظاهر اتوماتیک به دولوپر ها ( حتی زبان های سطح بالا ) این اطمینان خاطر اشتباه رو میده که نباید دیگه به مدیریت حافظه فکر بکنند. که این جور فکر کردن اشتباه بزرگی هست. حتی موقع کار کردن با زبون های سطح بالا هم, دولوپر ها باید درکی از مدیریت حافظه داشته باشن ( یا حد اقل اصول پایه ای اون رو بدونن ). گاهی وقتا فرایند اوتوماتیک مدیریت حافظه, مشکلاتی رو به همراه خودش داره ( مثل باگ ها یا محدودیت ها در پیاده سازی گاربج کالکتور و ... ) که دولوپر ها برای کنترل کردن این مشکل ها باید اون هارو درک کرده باشن ( یا یه روشی برای دور زدن پیدا کنن که کمترین trade off و قانون شکنی و پا گذاشتن روی اصول رو داشته باشه ).چرخه ی عمر حافظه - Memory life cycleمهم نیست که چه زبونی رو دارید استفاده میکنید ولی عموما چرخه ی عمر حافظه بین اون ها یک شکل هست :این یه توضیح مختصر از اتفاقاتی که تو هر قدم از چرخه رخ میده هست:اشغال حافظه: حافظه ی اشغال شده و در حقیقت رزور شده توسط سیستم عامل برای برنامه ی شما که این امکان رو میده تا از این حافظه در برنامه استفاده بشه. تو زبان های سطح پایین مثل C این یک فرایند مستقیم هست که دولوپر باید اون رو کنترل کنه. اما تو زبان های سطح بالا این فرایند برای شما به طور خودکار انجام میشه. استفاده از حافظه: قدمی هست که در واقع برنامه ی شما از حافظه از قبل اشغال شده استفاده میکنه. وقتی که شما از متغیر ها اشغال شده توی کدتون استفاده میبرید فرایند خوندن و نوشتن در همین قدم اتفاق میوفته.رها سازی حافظه: حالا وقت آزاد کردن و در دسترس قرار دادن مجدد همه ی حافظه ای هست که شما دیگه به اون احتیاج ندارید. مثل اشغال کردن حافظه این فرایند هم تو زبان های سطح پایین به طور مستقیم باید مدیریت بشه.برای مرور سریع بر مفاهیم پشته فراخوانی و پشته ی حافظه میتونید پست اول این سری رو بخونید.حافظه چیست؟ قبل از این که بپریم وسط حافظه تو جاوا اسکریپت, بهتره خیلی خلاصه وار در مورد ماهیت عمومی حافظه و چه جوری کار کردنش بحث کنیم. تو سطح سخت افزاری, حافظه ی کامپویتر تشکیل شده از کلی flip flop. هر فلیپ فلاپ از تعدادی ترانزیستور ساخته شده و یک بیت جا داره. تعدادی فلیپ فلاپ منحصر به فرد با یه شناسه ی منحصر به فرد در دسترس هستن, که به کمک این شناسه بتونیم اون هارو بخونیم یا روشون مجددا بنویسیم. با این حال به طور مفهومی میتونیم کل حافظه ی کامپیوترو یه آرایه خیلی بزرگ ببینیم که میتونیم روش بنویسیم و ازش بخونیم.و ازون جایی که آدمی زاد زیاد تو انجام محاصبات و فکر کردن هاش به سبک بیتی خوب نیست, سعی کرده اون هارو به گروه های بزرگتری دسته بندی کنه, که با هم دیگه میشه اعداد رو نشون داد.خیلی چیزا تو حافظه نگه داری میشه. تمام متغیر ها و داده هایی که توسط برنامه ها استفاده میشن.کد برنامه نویس ها, شامل سیستم عامل هم میشهکامپایلر و سیستم عامل اکثر کارهای مدیریت حافظه رو برای ما انجام میدن اما ما پیشنهاد می کنیم یه سرکی به اتفاق هایی که این دو برای مدیریت حافظه انجام میدن بکشید. وقتی شما کدتون رو کامپایل میکنید, کامپایلر میتونه تایپ های متغیر های شمارو ببینه و قبل اجرا محاسبه کنه که چقدر حافظه نیاز دارن. مقدار مورد نیاز حافظه تو فضای پشته stack space برای برنامه اشغال میشه. به فضایی که این متغیر ها در اون نگهداری میشن فضای پشته گفته میشه بخاطر این که وقتی تابع ها فراخوانی میشن, حافظه ی اون ها بالای همه ی حافظه اضافه میشه. و وقتی هم که از بین میرن, به ترتیب LIFO last-in, last-out حذف میشن. برای مثال این معرف هارو ببینید:‌int n; // 4 bytes
int x[4]; // array of 4 elements, each 4 bytes
double m; // 8 bytesکامپایلر به سرعت تشخیص میده که این کد نیاز به 4 + 4 × 4 + 8 = 28 bytes حافظه داره.با سایز الان اینتجر و دابل کامپایلر یه همچین محاسبه ای رو داره. حدود ۲۰ سال پیش اینتجر ۲ بایت و دابل ۴ بایت فضا داشته. برای الان لازم نیست که کد شما بدونه بایت و اینتجر چقدر فضا اشغال میکنن.کامپایلر کد هایی رو اضافه میکنه که با سیستم عامل در جهت درخواست بایت های مورد نیاز روی استک برای ذخیره شدن متغیر ها ما تعامل میکنه. تو مثال بالا کامپایلر آدرس دقیق هر متغیر رو میدونه. در حقیقت وقتی ما چیزی رو در متغیر n قرار میدیم, n ترجمه میشه به یه چیزی مثل این: &quot;آدرس حافظه 4127963&quot;.به این توجه کنید که اگر بخوایم به خونه ی چهارم آرایه x دسترسی داشته باشیم, ممکنه به داده ای که در فضای متغیر m هست دسترسی پیدا کنیم. این به این خاطر هست که المان چهارم در آرایه x وجود نداره. این خونه چهارم چهار بایت دور تر از آخرین المان ذخیره شده در فضای آخرین المان ارایه x است که ممکنه تعامل ما باهاش باعث خونده شدن (اور رایت کردن) قسمتی از بیت های حافظه ی متغیر m بشه. خب این اتفاق اگر بیوفته مشخصا عواقب خوبی برای اجرای بقیه برنامه نداره.وقتی تابعی یه تابع دیگه رو فراخوانی میکنه, هر کدوم از این تابع ها قسمت مورد نیاز خودشون رو از استک میگیرن. تمام متغیر های داخلی خودشون رو تو قسمتی که بهشون اختصاص داده شده میذارن, اما شمارنده ی برنامه هم جایی که برنامه در حال اجرا هست رو در خودش نگه داری میکنه. وقتی اجرا تابع به پایان رسید حافظه ای که برداشته برای استفاده های دیگه مجددا آزاد میشه. اختصاص گیری پویا - Dynamic allocationمتاسافنه, وقتی نمیدونیم چقدر حافظه رو باید اختصاص بدیم به یه برنامه تو زمان کامپایل محاسبات سخت میشه و آسون نیست دیگه. فرض کنید میخوایم یه همچین کاری کنیم:int n = readInput(); // reads input from the user...// create an array with &quot;n&quot; elementsاین جا تو زمان کامپایل, کامپایلر نمیتونه تشخیص بده که آرایه n چقدر حافظه نیاز داره چرا که این اندازه رو مقداری که کاربر مشخص کرده تعیین میکنه. به همین منظور کامپایلر نمیتونه جایی رو برای این متغیر توی استک در نظر بگیره. به جاش برنامه نیاز داره به طور مستقیم از سیستم عامل بخواد که تو زمان اجراش حافظه ی مورد نظر رو بهش اختصاص بده. این حافظه از heap space اختصاص داده میشه. تفاوت اختصاص حافظه ی استاتیک و داینامیک رو به طور خلاصه در جدول زیر میبینید:اختصاص حافظه در جاوا اسکریپتجاوا اسکریپت متغیر هارو از مدیریت کردن حافظه معاف کرده و این کار رو خودش در کنار تعریف کردن متغیر ها انجام میده.  var n = 374; // allocates memory for a number
var s = &#039;sessionstack&#039;; // allocates memory for a string var o = {
  a: 1,
  b: null
}; // allocates memory for an object and its contained valuesvar a = [1, null, &#039;str&#039;];  // (like object) allocates memory for the
                           // array and its contained valuesfunction f(a) {
  return a + 3;
} // allocates a function (which is a callable object)// function expressions also allocate an object
someElement.addEventListener(&#039;click&#039;, function() {
  someElement.style.backgroundColor = &#039;blue&#039;;
}, false);فراخوانی بعضی از تابع ها نتیجش اخصاص فضا به آبجکت هاست:var d = new Date(); // allocates a Date objectvar e = document.createElement(&#039;div&#039;); // allocates a DOM elementتابع ها قابلیت اختصاص دادن حافظه متغیر ها و آبجکت هارو دارن.var s1 = &#039;sessionstack&#039;;
var s2 = s1.substr(0, 3); // s2 is a new string
// Since strings are immutable, 
// JavaScript may decide to not allocate memory, 
// but just store the [0, 3] range.var a1 = [&#039;str1&#039;, &#039;str2&#039;];
var a2 = [&#039;str3&#039;, &#039;str4&#039;];
var a3 = a1.concat(a2); 
// new array with 4 elements being
// the concatenation of a1 and a2 elementsاستفاده از حافظه در جاوا اسکریپتاستفاده از حافظه در جاوا اسکریپت به معنی خوندن و نوشتن حافظه است. این کار هم با خوندن و نوشتن متغیر ها یا پاس دادن آرگیومنتی به تابع اتفاق بیوفته.رها کردن حافظه در زمانی که دیگر نیازی بهش نیستاکثر مشکلات مدیریت حافظه در این مرحله رخ میده. قسمت سخت قضیه اینه که متوجه بشیم که دقیقا کی حافظه ی اختصاص شده دیگه مورد نیاز نیست. گاهی هم به عهده ی دولوپر هست که کجای برنامه دیگه نیاز به اون تیکه از حافظه نیست و خودش اون رو آزاد کنه.زبان های سطح بالا گاربج کالکتوری رو در خودشون دارن که کارش دنبال کردن حافظه ی اختصاص داده شده و استفاده از اون هست تا بتونه تشخیص بده کی دیگه اون حافظه مورد نیاز نیست و اون رو خالی کنه.متاسفانه این فرایند تقریبی هست و فهمیدن این که کدوم حافظه دیگه مورد نیاز نیست توسط الگوریتم ها قابل انجام نیست. اکثر گاربج کالکتور ها با حافظه هایی که دیگه در دسترس نیستن کار میکنن. برای مثلا تمام متغیر هایی که به اون قسمت از حافظه اشاره میکنن از اسکوپ اجرایی خارج شدن. این نوع از حافظه ها امکان آزاد سازی دارن هرچند که ممکنه درجای دیگه ای از برنامه متغیری به اون ها اشاره کنه ولی چون در ادامه برنامه نیازی به دسترسی پیدا کردن به اون حافظه و متغیر رو نداریم آزاد سازی اون مشکلی ایجاد نمیکنه.گاربج کالکشنبر اساس این که حقیقت که ما به طور قاتع نمیتونیم بگیم کدوم قسمت از حافظه دیگه مورد نیاز نیست. گاربج کالکتور ها قسمتی از یک راه حل عمومی رو پیاده سازی کردن. در این قسمت به مفاهیم لازم برای فهم اساس الگوریتم گاربج کالکتور ها و محدودیت هاشون میپردازیم. مرجع های حافظه - Memory referencesتو اینجا مفهوم آبجکت چیزی فراتر از آبجکت های معمولی جاوا اسکریپت و اسکوپ توابع و یا lexical scope هست.لکسیکال اسکوپ تکلیف اسم متغیر هارو تو تابع ها تو در تو مشخص میکنه: تابع های داخلی به اسکوپ تابع بیرونی دست رسی دارن حتی اگر تابع بیرونی چیزی رو ریترن کرده باشه. یکی از مفاهیم اصلی گاربج کالکتور ها بر اساس مرجع هست. در حوزه ی مدیریت حافظه, درصورتی آبجکت a میتونه مرجعی از آبجکت b رو داشته باشه که بشه از a به b رسید. ( این دسترسی به طور مستقیم و غیر مستقیم میتونه وجود داشته باشه. ) برای مثال آبجکت جاوا اسکریپت به پروتو تایپ خودش به صورت غیر مستقیم ( یعنی اگه به پروتو تایپ یه فانکشن یا پراپرتی بدیم نیازی نیست که بنویس a.prototype.whatever فقط کافیه بنویسیم a.whatever) دسترسی داره و به طور مستقیم به پراپرتی های خودش. شماره ارجاع ها گاربج کالکشناین ساده ترین الگوریتم گاربج کالکشن هست. یه آبجکت زمانی قابلیت آزاد سازی داره که هیچ چیزی بهش ارجاع داده نشده باشه. به این قطعه کد نگاه کنید: var o1 = {
  o2: {
    x: 1
  }
};// 2 objects are created. 
// &#039;o2&#039; is referenced by &#039;o1&#039; object as one of its properties.
// None can be garbage-collectedvar o3 = o1; // the &#039;o3&#039; variable is the second thing that 
            // has a reference to the object pointed by &#039;o1&#039;.                                                       
o1 = 1;      // now, the object that was originally in &#039;o1&#039; has a         
            // single reference, embodied by the &#039;o3&#039; variable

var o4 = o3.o2; // reference to &#039;o2&#039; property of the object.
                // This object has now 2 references: one as
                // a property. 
                // The other as the &#039;o4&#039; variable

o3 = &#039;374&#039;; // The object that was originally in &#039;o1&#039; has now zero
            // references to it. 
            // It can be garbage-collected.
            // However, what was its &#039;o2&#039; property is still
            // referenced by the &#039;o4&#039; variable, so it cannot be
            // freed.

o4 = null; // what was the &#039;o2&#039; property of the object originally in
           // &#039;o1&#039; has zero references to it. 
           // It can be garbage collected.چرخه ها باعث مشکلات هستند (ارجاع های تو در تو a به b و b به a)تو این راه حل محدودیت هایی روی چرخه ها وجود داره. تو مثالی که داریم دو تا آبجکت ساخته شدن و به هم ارجاع داده شدن, به همین منظور یک چرخه رو به وجود آوردن. اون ها بعد از فراخوانی تابع از اسکوپ خارج و بی کاربرد میشن پس میشه حافظه اون ها رو آزاد کرد. اما الگوریتم شمارنده ارجاع ها اینجوری برداشت میکنه که حد اقل یک رفرنس به هردوی این آبجکت ها وجود داره پس نمیشه حافظه ی اون هارو آزاد کرد. function f() {  var o1 = {};  var o2 = {};  o1.p = o2; // o1 references o2  o2.p = o1; // o2 references o1. This creates a cycle.}f(); الگوریتم mark-and-sweepسه قدم این الگوریتمریشه ها: به طور عمومی ریشه های متغیر های گلوبال هستن که در کد بهشون ارجاع داده میشه. به طور مثال در جاوا اسکریپت متغیر گلوبالی که مثل یک ریشه رفتار میکنه آبجکت window هست. آبجکت مشابه در nodejs به اسم global هست. لیست کاملی از ریشه ها توسط گاربج کالکتور ساخته میشه. این الگوریتم تمام ریشه ها و فرزندان اون ریشه رو بررسی میکنه و اون هارو در حالت اکتیو نشانه گذاری میکنه ( یعنی اونهارو نباید دور بریزیم ).در نهایت گاربج کالکتور تمام حافظه ای که با اکتیو نشانه گذاری نشده رو به سیستم عامل برمیگردونه.این الگوریتم از قبلیه بهتره چون آبجکتی که هیچ رفرنسی نداشته باشه به آبجکتی تبدیل شده که دیگه نیاز به دسترسی بهش نداریم اما برعکس این قضیه تو الگوریتم اول صادق نبود. یعنی آبجکتی بهش دسترسی نداریم ممکنه به کمک چرخه ها هنوز رفرنسی داشته باشه. از ۲۰۱۲ تمام مرورگر های مدرن دارن از mark-and-sweep استفاده میکنن. تمام بهبود هایی که اتفاق افتاده (generational/incremental/concurrent/parallel garbage collection) اثر بهتر کردن پیاده سازی این الگوریتم هست. اما خود اصل الگوریتم و هدفش که که تشخیص دادن در دسترس بودن یه آبجکت هست بهتر نشده. تو این مقاله میتونید بهینه سازی خود الگوریتم رو بخونید. چرخه ها دیگه مشکل ساز نیستنددر اولین مثال بالا بعد از این که تابع چیزی رو ریترن میکنه دو آبجکت دیگه ارجاعی ندارن از آبجکت گلوبال. در نتیجه حافظه اونها توسط گاربج کالکتور آزاد میشه.هرچند که این دو آبجکت به هم رفرنس دارن ولی توسط ریشه دیده نمیشن و حافظه ای که اشغال کردن باید آزاد بشه. رفتار های غیر معمول گاربج کالکتور هاهرچند که گاربج کالکتور ها راه حل عمومی و مناسبی هستند ولی مشکلات خودشون رو هم دارن.یکی از اونها قاطعیت در تصمیم گیری هست. به زبانی دیگر یعنی گاربج کالکتور ها غیر قابل پیش بینی هستند. دقیقا نمیشه گفت چه زمانی گاربج کالکتور شروع به جمع آوری حافظه ها میکنه و این به این معنا هست که بعضی وقت ها برنامه ها حافظه ی بیشتر از نیاز خودشون رو در اختیار میگیرن. تو حالت های مختلف این مورد باعث وقفه هایی در اجرا تو برنامه های حساس میشه. هر چند که قاطع نبودن گاربج کالکتور ها به این معنی هست که معلوم نیست کی شروع به اجرای جمع آوری بکنن, اما اکثر اون ها یک پترن مشابه رو جمع آوری حافظه بعد از اختصاص دادن حافظه به برنامه دارن. اگر اختصاص حافظه ای به برنماه صورت نگیره اکثر گاربج کالکتور ها به صورت آیدل و بی کار در میان و کاری نمیکنن. این سناریو رو در نظر بگیرید: مقدار قابل توجهی از حافظه به برنامه اختصاص داده میشه.اکثر این حافظه ها به دلیل غیر قابل دسترس بودن علامت گذاری میشن ( به فرض ما نال کردیم پوینتری رو که به اطلاعات کش ما دسترسی داشت و دیگه بهش نیاز نداریم )دیگه هیچ اختصاص حافظه ای رخ نده. تو این سناریو اکثر گاربج کالکتور ها, شروع به جمع آوری حافظه نمیکنند. هر چند که این حافظه ها دیگر در دسترس نیستند ولی کالکتور ها اقدام به جمع آوری آن ها نمیکنند. به طور قطعی نمیتوان گفت همه این حافظه ها باید جمع آوری بشوند ولی دلیلی بر غیر معمول و زیاد بودن حجم حافظه ی در حال استفاده هستند.مموری لیک ها چه هستند؟همانطور که حافظه نشون میده، مموری لیک قطعاتی از حافظه ای است که برنامه در گذشته استفاده کرده اما دیگه نیازی به اون ها نیست اما هنوز به سیستم عامل و یا مجموعه حافظه آزاد برنگشتن.زبان های برنامه نویسی برای مدیریت حافظه روش های متفاوتی نسبت به همدیگه پیاده سازی کردن. تصمیم گیری قاطع در مورد یک تکه از حافظه که استفاده شده یا نه یک مساله ی غیر قابل حله و بهتر بگم این توسعه دهند ها هستند که در نهایت تصمیم میگیرند که یک تکه از حافظه آزاد بهد و به سیستم عامل بازگرده یا نه.بعضی از زبان های برنامه نویسی برای مدیریت حافظه ابزاری رو برای توسعه دهنده ها فراهم کردن. بعضی از اون ها هم از برنامه نویس انتظار دارن که زمان آزاد شدن حافظه رو مشخص کنه. 4 نوع متدوال از مموری لیک در جاوا اسکریپت‍۱: متغیر های گلوبال جاوا اسکریپت روش جالبی برای هندل کردن متغیر های تعریف نشده داره: وقتی به یک متغیر تعریف نشده ارجاع میدیم, یک متغیر در آبجکت گلوبال ساخته میشه. تو مرورگر متغیر گلوبال window هست. به این معنی که: function foo(arg) { 
     bar = &quot;some text&quot;;
 }برابر هست با function foo(arg) {
    window.bar = &quot;some text&quot;;
}بر فرض این که تنها استفاده از متغیر bar در تابع foo باشد بعد از اجرا تابع foo یک متغیر بی خودی گلوبال bar درست شده. اگر از کیورد var برای متغیر ها استفاده کنیم متغیر گلوبالی به وجود نمیاد. البته هنوز سناریو های بد تری هم میشه تصور کرد. میشه حتی تصادفی به کمک this هم یه متغیر global ساخت:function foo() {     
    this.var1 = &quot;potential accidental global&quot;; 
}// Foo called on its own, this points to the global object (window)
// rather than being undefined.
foo();با استفاده از use sctrict در اول اسکریپت, پارسر جاوا اسکریپت سخت گیرانه تر برخورد میکنه و از ساخته شدن همچین متغیر هایی جلوگیری میکنه.متغیر گلوبال ناخواسته, قطعا یه مشکله هر چند که تو کد های خودمون هم از متغیر های گلوبال استفاده کردیم که قاعدتا گاربج کالکت نمیشن. توجه خاصی باید به متغیر های گلوبالی داشته باشیم که دیتای موقتی رو نگه میدارن یا دیتایی که پراسس بالایی روش هست. اگر مجبور هستید از متغیر های گلوبال استفاده کنید و هر جا که دیگه نیازی نیست به اون ها یا نال کنید یا مقدار دیگری رو درش ذخیره کنید.۲: تایمر ها و کالبک هایی که فراموش شدنبزارید به تابع setInterval اشاره کنیم که تو کدهامون استفادش میکنیم.کتابخونه هایی که observers و یا ابزار هایی که کالبک قبول میکنن همیشه سعی میکنن این مورد هارو بعد از اتمام کارشون از دسترس خارج کنن هر چند که نمونه کد پایین رو هنوز میشه تو بعضی از کار ها پیدا کرد: var serverData = loadData(); 
var interval = setInterval(function() {     
    var renderer = document.getElementById(&#039;renderer&#039;);    
    if(renderer) {
           renderer = JSON.stringify(serverData); 
           clearInterval(interval);    
     }
 }, 5000); //This will be executed every ~5 seconds.در تکه کد بالا استفاده از اچ تی ام ال نود و دیتایی رو تو setInterval میبینیم که بعد از یک بار اجرا دیگه بهشون احتیاجی نیست. (مثلاش جالب نیست میدونم ولی حرفای بعدش خوبه). خب اگر تو فرایند برنامه ابجکت renderer حذف یا با چیز دیگه ای جایگزین بشه هیچ وقت این ست اینتروال به سرانجام نمیرسه و چون در تابعی که داره از serverData داره استفاده میکنه گاربج کالکتور هیچوقت نمیتونه این داده رو که ممکنه کلی پراسس و رم رو مشغول کرده حذف کنه. وقتی داریم از Observer ها استفاده میکنیم بهتره بعد از اتمام کارمون, اون هارو هم حذف کنیم. ( چه زمانی که دیگه به ابزرور نیازی نداریم و یا نودی که داریم ابزروش میکنیم دیگه در دسترس نیست )خوشبختانه اکثر مرورگر های مدرن این کارو برای ما به طور خودکار انجام میدن. به طور اوتوماتیک وقتی یه آبجکتی دیگه در دسترس نباشه تمام آبزرور هاش رو کالکت میکنن حتی اگر ما یادمون رفته باشه که اون هارو حذف کنیم در کد.البته یه مرورگر مثل IE6 خیلی خسته تر از این حرفا هست که این کار هارو انجام بده. اما جزو بست پرکتیس ها هست که وقتی آبجکتی از روند اجرایی برنامه خارج میشه, این آبزرور هارو  تو لایه کد حذف کنیم. به مثال زیر دقت کنید:var element = document.getElementById(&#039;launch-button&#039;);
var counter = 0;function (event) {
   counter++;
   element = &#039;text &#039; + counter;
}element.addEventListener(&#039;click&#039;, );// Do stuffelement.removeEventListener(&#039;click&#039;, );
element.removeChild(element);// Now when element goes out of scope,
// both element and  will be collected even in old browsers // that don&#039;t handle cycles well.
البته باز اشاره کنیم که شما دیگه لازم نیست در لایه کد تابع removeEventListener رو قبل از این که نود اچ تی ام ال از دسترس خارج بشه فراخوانی کنید, چون مرورگر های مدرن این رفرنس سایکل هارو پیدا میکنه و اونهارو گاربج کالکت میکنه. اگر هم که از کتابخونه ی jquery استفاده میکنید ( البته بقیه لایبرری ها هم به خوبی از این قضیه پشتیبانی میکنند ) میتونید قبل از از دسترس خارج شدن نود اچ تی ام ال لیسنرهایی که به اون بایند کردین رو حذف کنید و کتابخونه هم مطمان میشه که مموری لیکی اتفاق نیوفتاده باشه حتی تو مرورگر های قدیمی. 3: کلوژر ها یکی از نقاط قوت جاوا اسکریپت کلوژر هاش هستن: تابع داخلی که به اسکوپ تابع بیرونی خودش دسترسی داره. با توجه به نحوه ی پیاده سازی رانتایم جاوا اسکریپت ممکن هست که به روش زیر مموری لیک داشته باشیم.var theThing = null;var replaceThing = function () { var originalThing = theThing;
  var unused = function () {
    if (originalThing) // a reference to &#039;originalThing&#039;
      console.log(&quot;hi&quot;);
  }; theThing = {
    longStr: new Array(1000000).join(&#039;*&#039;),
    someMethod: function () {
      console.log(&quot;message&quot;);
    }
  };
};setInterval(replaceThing, 1000);وتقی replaceThing فراخوانی میشه, theThing با یه آبجکت پر میشه که شامل یک آرایه بزرگ و یک کلوژر به نام someMethod هست. در عین حال متغیر originalThing توسط یک کلوژری که در unused هست استفاده شده ( که در حقیقت originalThing رفرنسش برمیگرده به فراخوانی قبلی تابع replaceThing به متغیر theThing ). چیزی که باید به یاد داشته باشیم هر چند تا کلوژری که ایجاد شده اسکوپ پرنت خودشون رو با هم در اشتراک دارن. در کد بالا someMethod و unused هر دو کلوژری هستند که اسکوپ replaceThing رو در اختیار دارن. unused اشاره ای به متغیر originalThing داره و هرچند که unused هیچ وقت صدا زده نمیشه اما  someMethod میتونه هر جای برنامه از روی آبجکت theThing فراخوانی بشه. و با توجه به این که اسکوپ تابع replaceThing با دو کلوژر  someMethod و unused در اشتراک هست صرف اینکه unused فقط اشاره ای به originalThing داره باعث میشه تمام اسکوپ replaceThing برای گاربج کالکتور اکتیو بمونه و هیچوقت کالکت نشه. تمام این داستان ها باعث یه مموری لیک خفن بشه. اگر این تیکه کد رو اجرا کنید هر چند ثانیه یه پیک استفاده از مموری ایجاد میشه که هروقت هم گاربج کالکتور اجرا بشه این پیک کمتر نمیشه. یه لیستی از کلوژر های بهم متصل شده که ریشه اون ها theThing هست درست کردیم و علاوه بر این اسکوپ هر کلوژر به طور غیر مستقیم اشاره میکنه به یک آرایه خیلی بزرگ.تیم میتیئور این مموری لیک رو پیدا کردن و در موردش تو این مقاله نوشتن. 3: در دسترس نبودن DOMمواردی هست که دولوپر ها نود های DOM رو توی دیتا استراکچر هایی نگه داری میکنن. فرض کنید شما میخواید سل های یه تیبل رو خیلی سریع به روز کنید و یک رفرنسی از اون هارو داخل یه دیکشنری (‌ابجکت جاوا اسکریپتی ) یا آرایه نگه داری کنید. این طوری دو تا رفرنس از هر سل ایجاد شده. یکی تو دیتا استراکچر شما و دیگر تو درخت DOM مرورگر. اگر میخواید سلی رو پاک کنید حواستون باشه که هر دو رفرنس رو باید حذف کنید. var elements = {
    button: document.getElementById(&#039;button&#039;),
    image: document.getElementById(&#039;image&#039;)
};function doStuff() {
    elements.image.src = &#039;http://example.com/image_name.png&#039;;
}function removeImage() {
    // The image is a direct child of the body element.
    document.body.removeChild(document.getElementById(&#039;image&#039;));   // At this point, we still have a reference to #button in the
    //global elements object. In other words, the button element is
    //still in memory and cannot be collected by the GC.
}باید خیلی مواظب باشید وقتی با برگ های درخت DOM یا همون نود های اچ تی ام ال داخلی کار میکنید. اگر توی کدتون رفرنسی از یه تگ td داخل یه تیبل داشته باشید و بعد از اون کل تیبل رو از DOM حذف کنید و از پس این حذف کردن انتظار داشته باشید که کل اون تیبل از مموری حذف میشه کور خوندید و سناریو ایجاد مموری لیک رو پیش گرفتید. چون تگ های اچ تی ام ال رفرنس به پرنت خودشون دارن و وجود این رفرنس در تگ td که در کد بهش دسترسی داریم باعث میشه هیچ وقت کل تیبل از مموری حذف نشه. تمام.</description>
                <category>Hassan Gilak</category>
                <author>Hassan Gilak</author>
                <pubDate>Wed, 22 Aug 2018 16:56:25 +0430</pubDate>
            </item>
                    <item>
                <title>جاوا اسکریپت چه جوری کار میکنه؟ دل و روده ی V8 engine و ۵ تا نکته در مورد کد بهینه نوشتن</title>
                <link>https://virgool.io/JavaScript8/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-f2jopafgjzxj</link>
                <description>سری &quot;جاوا اسکریپت چه جوری کار میکنه؟&quot; بازگردن مقاله های Alexander Zlatkov به زبون خودم هست. هدف از این کار در مرحله ی اول یادگیری خودم و انتشار این مقاله به فارسیه.قرارم بر این نیست که همه کلمات رو به فارسی بگم به این دلیل که اگر خواستید بیشتر جستو جو داشته باشید در مورد کلمات کلیدیش, بتونید راحت تر این کارو انجام بدین.اهمیت این نوشته برای من محتواش هست نه طرز بیان یا نگارشش. ممنون میشم اگر که هم در محتوا هم در طرز بیان یا نگارش اشکالی هست بیان کنید تا بتونم بهترش کنم.بازگردانی شده از : How JavaScript works: inside the V8 engine + 5 tips on how to write optimized codeهفته ها پیش, ما یه سری رو در مورد درک عمقی تر از جاوا اسکریپت و چه جوری کار کردنش رو شروع کردیم: ما فکر میکردیم که با دونستن اجزای تشکیل دهنده جاوا اسکریپت و تعاملشون با هم شما میتونید کدها و برنامه های بهتری بنویسید.اولین مطلب این سری تمرکزش روی مرور رو موتور جاوا اسکریپت, رانتایم و پشته اجرایی بوده. اما تو این یکی پست شیرجه میزنیم تو دل و روده ی موتور V8. همچنین یه سری نکته در مورد بهتر کد نوشتن هم فراهم میکنیم ( بست پرکتیس هایی که تیم توسعه ی SessionStack  موقع ساخت این محصول پیروی میکردن ). بررسی کوتاهموتور جاوا اسکریپت یه برنامه یا یه مترجم هست که کدهای جاوا اسکریپت رو اجرا میکنه. این موتور میتونه به دو صورت عمل کنه. مترجم استاندارد یا یه کامپایلر در لحظه (just in time compiler) که کد هارو تبدیل به یه نوع بایت کد میکنه.این یه لیست از پروژه های معروفی هست که موتور جاوا اسکریپت رو پیاده سازی کردن:موتور V8 - اوپن سورس, توسعه داده شده توسط گوگل, نوشته شده با ++cموتور Rhino - توسط سازمان موزیلا مدیریت میشه, اوپن سورس, به طور کامل با جاوا نوشته شدهموتور SpiderMonkey - اولین موتور جاوا اسکریپت, که قبل ها توسط نت اسکیپ استفاده میشده و الان هم فایرفاکسموتور JavascriptCore - اوپن سورس, به اسم Nitro معرفی شده و توسط اپل توسعه داده میشه برای مرورگر سافاریموتور KJS - موتور KDE که در حقیقت توسط Harri Porten برای یه پروژه KDE به نام مرورگر Konqueror توسعه داده شدهموتور (Chakra (JScript9 - اینترنت اکسپلوررموتور (Chakra (JavaScript - مایکروسافت اجموتور Nashron - اوپن سورس که قسمتی از OpenJDK هست که با Oracle Java و Tool Group نوشته شدهموتور JerryScript - یه موتور سبک برای اینترنت اشیا.چرا موتور V8 ساخته شد ؟این موتور توسط گوگل ساخته شده و با سی پلاس پلاس نوشتنشو داخل گوگل کروم و nodejs استفاده میشه.موتور V8 اولین بار برای افزایش کارایی اجرایی جاوا اسکریپت داخل مرورگر ساخته شده. برای افزایش سرعت, موتور V8 کد های جاوا اسکریپت رو تبدیل به کدهای ماشین بهینه تری میکرد تا این که فقط اون هارو ترجمه کنه. موتور V8 مثل اکثر موتور های مدرن جاوا اسکریپتی مثل Rhino و SpiderMonkey کد های جاوا اسکریپت رو به کد های ماشی تو زمان اجرا با تکنین (JIT (Just-In-Time کامپایلر تبدیل میکنه. اما تفاوت اصلی اینجاست که موتور V8 بایت کد یا کد میانی تولید نمیکنه.موتور V8 قبلا دو کامپایلر داشتهقبل از نسخه ی 5.9 موتور V8 که اولای ۲۰۱۷ اومده از دو تا کامپایلر سود میبرده:کامپایلر full-codegen - کامپایلری ساده و سریع که کدهای ماشین ساده و کند تولید میکنهکامپایلر CrankShaft - کامپایلری بهینه تر و پیچیده تر که از تکنین Just-In-Time برای تولید کد های بسیار بهینه استفاده میکنه. موتور V8 ترد های داخلی متعددی رو هم به کار میگیره: ترد اصلی کاری که ازش انتظار داریم رو انجام میده: کد هارو میگیره, کامپایل و اجرا میکنهیه ترد دیگه هم برای کامپایل وجود داره که ترد اصلی بتونه به کارش ادامه بده تا قبلیه بتونه کار بهینه سازی رو همزمان پیش ببرهیه ترد پروفایلر که به رانتایم میگه ما رو کدوم تابع زیاد وقت گذاشتیم تا کامپایلر CrankShaft بتونه بهینش کنهچند تا ترد دیگه که کار گاربج کالکشن رو انجام میدناولین باری که کد جاوا اسکریپت شما اجرا میشه, موتور V8 از کامپایلر full-codegen استفاده میکنه که کد جاوا اسکریپت پارس شده رو مستقیما به کد ماشین ترجمه میکنه اون هم بدون هیچ تغییری. این کار اجازه میده تا شروع اجرای کدهای ماشین خیلی سریع بشه. این نکته رو هم در نظر داشته باشید که موتور V8 از بایت کدهای واسط استفاده نمیکنه و با این روش نیاز به مفسر رو حذف کرده.وقتی کد شما برای مدتی تو مرحله ی اجرا باشه, ترد پروفایلر اطلاعات کافی رو پیدا کرده تا بگه کدوم تابع ها باید بهینه بشن.تو مرحله ی بعدی, کامپایلر CrankShaft کار بهینه سازیشو روی ترد دیگه ای شروع میکنه. این کامپایلر میاد درخت انتزاعی سینتکس abstract syntax tree - AST رو به تک تخصیصی استاتیک  static single-assignment - SSA (خیلی سخته ترجمشون :)) ) سطح بالا تبدیل میکنه که به نام Hydrogen شناخته میشه. و بعد تلاش میکنه بهینه سازی رو روی گراف هیدروژن انجام بده.اکثر این بهینه سازی ها روی همین گراف رخ میده.خطی سازیاولین بهینه سازی خطی کردن روی خطوط واجد شرایط میباشد. خطی سازی پروسه ی جابه جایی منطقه ی فراخوان شده ( لاین خط کدی که تابع فراخوانی شده) با بدنه اون تابع هست. این روش ساده اجازه میده تا بهینه سازی های بعدی بهتر معنی پیدا کنن. کلاس های مخفی - Hidden Classes( قبل از این که این پاراگراف رو به فارسی برگردونم لطفا کنسول خودتون رو باز کنید و این تیکه کد رو اجرا کنید. ممکنه براتون سوال بشه که چرا میگه جاوا اسکریپت پروتو تایپ بیس هست درصورتی که ما کیورد class رو هم داریم. اریک الیوت یه مقاله خیلی طولانی در موردش نوشته که جزو سری &quot;تو مصاحبه های جاوا اسکریپت حرفه ای بشید&quot; هستش  )class Foo {}
typeof Fooجاوا اسکریپت زبان پروتوتایپ بیسی هست و این به این معنیه که کلاسی و آبجکتی وجود نداره که با کلون کردن درسته بشه. جاوا اسکریپت یه زبون داینامیکه, این یعنی اینکه میشه بعد از ساخت یه آبجکت پراپرتی اضافه کم بشه.اکثر مترجم های جاوا اسکریپتی از یه ساختمون دیکنشری طور (hash function based) برای نگه داری پراپرتی های یک آبجکت توی حافظه استفاده میکنن. این استراکچر باعث میشه تا دسترسی به مقدار یه پراپرتی تو جاوا اسکریپت هزینه محاسباتی بیشتری داشته باشه نسبت به زبان های غیر داینامیک مثل جاوا و سی شارپ. تو جاوا همه ی پراپرتی های یه آبجکت قبل از کامپایل توسط یه لایه آبجکت ثابت مشخص شدن و موقع رانتایم نمیشه به صورت داینامیک اون هارو کم یا زیاد کرد. ( البته سی شارپ داینامیک تایپ داره که یه موضوع دیگست اون). در نهایت مقدار پراپرتی ها (یا پوینتر اون پراپرتی ها) رو میشه به تو بافر روی مموری بایه فاصله مشخص نگه داری کرد. مقدار فاصله رو میشه به راحتی بر اساس نوع پراپرتی ها مشخص کرد اما برای جاوا اسکریپت امکان پذیر نیست چون میشه ماهیت یه پراپرتی تو رانتایم عوض بشه.با توجه به این که نگه داشتن لوکیشن پراپرتی ها با دیکشنری روی رم هزینه بر هست موتور V8 روش دیگری رو به نام کلاس های مخفی استفاده میکنه. کلاس های مخفی از لحاظ عملکرد شبیه لایه ثابت آبجکتی تو زبون جاوا و زبون های مشابهش هستن با این تفاوت که تو زمان رانتایم ساخته میشن. خب حالا ببینیم که واقعا چه جوری کار میکنن: function Point(x, y) {
    this.x = x;
    this.y = y;
}var p1 = new Point(1, 2);
وقتی که فراخوانی”new Point(1,2)“ اتفاق میوفته, موتو V8 یه کلاس مخفی به نام C0 درسته میکنه :تو این مرحله هیچ پراپرتی برای Point معرفی نشده پس C0 خالیه.  وقتی که اولین عبارت &quot;this.x = x&quot; اجرا شد(داخل تابع Point), موتور V8 کلاس مخفی دومی میسازه به نام &quot;C1&quot; که بر اساس &quot;C0&quot; بنا شده. &quot;C1&quot; اشاره میکنه به مکانی تو حافظه که ( مرتبط با آبجکت پوینتر ) پراپرتی x رو میشه پیدا کرد. تو این مورد x تو خونه 0 ذخیره شده, این به این معنیه که وقتی داریم آبجکتی که از تابع point رو میبینم اولین خونه از اون آبجکت تو کانتینیوس بافری که روی رم داره پراپرتی x هست. موتور V8 هم &quot;C0&quot; رو با &quot;جابه‌جایی کلاس&quot; به روز میکنه که بیان میکنه پراپرتی &quot;x&quot; به آبجکت point اضافه شده که در این حالت موتور V8 باید کلاس مخفی &quot;C0&quot; به &quot;C1&quot; سوییچ کنه. کلاس مخفی حال حاضر آبجکت point سی وان هست.هر بار که یه پراپرتی به یه آبجکتی اضافه میشه, کلاس مخفی قبلی با اضافه شدن جابه‌جایی به کلاس مخفی جدید به روز میشه. این جابه‌جایی ها روی کلاس های مخفی به این دلیل مهم هستن که به کلاس های مخفی اجازه میده تا با آبجکت هایی که فرایند ساخت و شکل گیری مشابه دارن, در اشتراک باشن. اگر دو تا آبجکت یک کلاس مخفی رو با هم به اشتراک بزارن و یه پراپرتی به هر دویه اونها اضافه بشه, عمل جابه‌جایی این تضمین رو میده که هر دو آبجکت یک کلاس مخفی جدید در اشتراک با هم داشته باشن و همه قابلیت های بهینه سازی رو براشون فراهم بشه.این پروسه ادامه پیدا میکنه وقتی عبارت &quot;this.y = y&quot; اجرا میشه (دوباره توی تابع Point دقیقا بعد از عبارت &quot;this.x = x&quot;).یه کلاس مخفی دیگه به نام &quot;C2&quot; ساخته شده, جابه‌جایی بین کلاس به &quot;C1&quot; اضافه شده که بیان میکنه اگر پراپرتی &quot;y&quot; به آبجکت Point اضافه شده ( که البته پراپرتی &quot;x&quot; رو از قبل داشته ). بعد از این تغییر کلاس مخفی باید &quot;C2&quot; باشه و آبجکت point باید به &quot;C2&quot; اشاره کنه. جابه‌جایی بین کلاس های مخفی مرتبط با ترتیب اضافه شدن پراپرتی به یه آبجکت هست. به تکه کد زیر نگاه کنید:function Point(x, y) {
    this.x = x;
    this.y = y;
}var p1 = new Point(1, 2);
p1.a = 5;
p1.b = 6;var p2 = new Point(3, 4);
p2.b = 7;
p2.a = 8;احتمالا تصور میکنید که &quot;p1&quot; و &quot;p2&quot; از یه کلاس مخفی و یه جابه‌جایی استفاده میکنه. خب در حقیقت اینجوری نیست. برای آبجکت &quot;p1&quot; اول پراپرتی &quot;a&quot; و بعد پراپرتی &quot;b&quot; اضافه میشه در صورتی که برای &quot;p2&quot; اول پراپرتی &quot;b&quot; و بعدش پراپرتی &quot;a&quot; اضافه میشه و به همین دلیل هست که p1 و p2 از کلاس مخفی متفاوتی استفاده میکنن و مسیر جابه‌جایی متفاوتی دارن. پس : تو این موارد بهتره که پراپرتی های داینامیک رو با یک ترتیب انجام بدیم تا کلاس های مخفی بینشون به اشتراک گذاشته بشه.کش کردن خطی موتور V8 از یه روش بهینه سازی دیگه ای هم برای زبان های داینامیک استفاده میکنه به نام کش کردن خطی. این روش تکیه زده بر بررسی و مشاهده فرایند فراخوانی مکرر یک تابع رو یه سری آبجکت مشابه. اطلاعات بیشتر در مورد نحوه ی کار این تکنیک رو اینجا بخونید.ما در باره ی مفهوم کلی کش کردن خطی تو این مقاله هم صحبت میکنیم البته اگه حوصله خوندن اون متن رو ندارید.خب چه جوری کار میکنه؟ موتور V8 یه کشی رو نگه میداره که حاوی نوع آبجکت هایی هست که اخیرا به تابع ها پاس داده شده و از همین اطلاعات استفاده میکنه تا فرضیاتی در مورد نوع آبجکتی هایی که قرار هست به عنوان پارامتر در فراخوانی های آینده در کد به این تابع ها پاس داده بشه داشته باشه. اگر موتور V8 امکان این رو که بتونه فرض خوبی رو نسبت به نوع آرگیومنتی (آبجکتی) که قرار هست به تابع پاس بده داشته باشه, میتونه فرایند پیدا کردن پراپرتی های یه آبجکت رو  رد کنه و به جاش از اطلاعاتی که به دست آورده از مشاهدات قبلیش استفاده کنه.خب مفهوم کلاس مخفی و کش کردن خطی چه جوری به هم مرتبط میشن؟ هر وقت یه متود روی آبجکت خاصی فراخوانی میشه, موتور V8 باید به کلاس مخفی اون آبجکت نگاه کنه تا خونه ی مورد نظر برای تابع رو پیدا کنه. بعد از دو بار صدا کردن موفق یک تابع از یک کلاس مخفی, موتور V8 فرایند پیدا کردن خونه ی مورد نظر رو کنار میزاره و مستقیم جای اون خونه رو به پوینتر آبجکت اضافه میکنه. برای هر فراخوانی تابع در آینده موتور V8 این پیش فرض رو داره که کلاس مخفی اون آبجکت تغییری نداشته و در نتیجه مستقیم میره سراغ آدرس حافظه ی اون پراپرتی (متود) که قبلا به پوینتر خود آبجکت اضافه کرده بوده که این باعث میشه سرعت اجرا رو خیلی بالا بره.همچنین کش کردن خطی دلیل اهمیت زیاد به اشتراک گذاری یک کلاس مخفی بین آبجکت های هم نوع رو نشون میده. اگر شما دو تا آبجکت از یه نوع رو بسازید با دو تا کلاس مخفی متفاوت ( همون طور که تو مثال چند خط بالاتر این کارو کردیم ), موتور V8 نمیتونه از کش کردن خطی استفاده کنه هرچند که نوع آبجکت ها یکی باشه, به این دلیل که : کلاس مخفی مرتبط با هر آبجکت, آدرس متفاوتی برای پراپرتی های خودشون دارن.اساسا دو آبجکت با هم یکین ولی ترتیب ساخته شدن پراپرتی های &quot;a&quot; و &quot;b&quot; متفاوت بوده.کامپایل به زبان ماشینبعد از این که گراف هیدروژن برای اولین بار بهینه شده, کامپایلر Crankshaft اون رو به پیاده سازی سطح پایین تری به نام Lithium تبدیل میکنه. اکثر پیاده سازی لیثیوم مختص آرکیتکچر هست. رجیستر الوکیشن هم تو همین مرحله رخ میده.در آخر, لیثیوم به کد های ماشین تبدیل میشه. و بعد چیزی به نام OSR: on-stack replacement اتفاق میوفته. قبل از این که ما شروع به کامپایل و بهینه سازی یه متود طولانی بکنیم, اون رو اجرا میکنیم (اشاره میکنه به دو کامپایلری بودن موتور V8 که وظایف اجرا و بهینه سازی رو بین دو کامپایلر تقسیم کرده). موتور V8 اجرای کند اولیشو به کل کنار نمیزاره بره سراغ نسخه ی بهینه شدش و در عوض کانتکست برنامه ( استک, رجیستری ها) رو تبدیل میکنه تا بتونه وسط اجرا به کد های بهینه شده اونها سوییچ کنه. این یه کار خیلی پیچیدست, با این توجه که موتور V8 تو مرحله آغازین کار جایگزاری کد هارو انجام داده. موتور V8 تنها موتوری نیست که قادر به انجام همچین کاریه.البته حفاظت هایی وجود داره به نام deoptimization های وجود داره که کد های بهینه شده رو به حالت قبلی برمیگردونه برای زمانی که فرضیات موتور V8 از مثلا لوکیشن یه پراپرتی روی یه کلاس مخفی دیگه درست از آب در نیاد دیگه. فرایند Garbage Collectionبرای گاربج کالکت کردن, موتور V8 از روش قدیمی و عمومی mark-and-sweep برای پاکر کردن نسل قدیمی استفاده میکنه. انتظار میره فرایند مارک کردن اجرای جاوا اسکریپت رو متوفق کنه. برای کنترل کردن هزینه های گاربج کالکت کردن و پایدار کردن اجرا, موتور V8  از روش مارک کردن افزایشی استفاده میکنه: به جای پیمایش کردن کل پشته, و تلاش برای مارک کردن هر آبجکت واجد شرایط, فقط قسمتی از پشته رو پیمایش میکنه و مجددا اجرای پشته رو ادامه میده. نقطه ی شروع پیمایش بعدی گاربج کالکتور روی پشته از همون جایی بوده که دفعه قبل تموم کرده. این روش کمک میکنه تا مکث های کوتاه تری بین اجرای برنامه رخ بده. همون طور که قبلا اشاره شده مرحله پاک کردن روی ترد جدا گانه ای صورت میگیره.مفسر Ignition و کامپایلر TurboFanبا ریلیز نسخه 5.9 در اوایل 2017, پایپ لاین اجرایی جدیدی معرفی شده. این پایپ لاین پرفورمنس بهتری داره و ریسورس حافظه ی کمتری تو برنامه های جاوا اسکریپتی استفاده میکنه. پایپ لاین جدید بر اساس مفسر Ignition و جدیدترین کامپایلر بهینه ساز موتور V8 به نام TurboFan ساخته شده.میتونید در مورد این موضوع تو بلاگ تیم V8 بیشتر بخونید.از وقتی نسخه 5.9 اومده, full-codegen و Crankshaft ( تکنولوژی هایی که در موتور V8 از 2010 استفاده میشده ) دیگه تو موتور V8 برای اجرای جاوا اسکریپت استفاده نشده چون تیم V8 درگیر اضافه کردن فیچر های جدید جاوا اسکریپت و بهینه سازی اون ها شده. بنچمارک بهبود کارایی موتور V8 روی وب و Node.jsاین بهتر شدن ها تازه اول راهه. مفسر Ignition و کامپایلر TurboFan راه رو برای بهینه سازی و افزایش کارایی جاوا اسکریپت صاف کردن و دارن کم کم حضور موتور V8 رو تو وب و Node.js کمرنگ میکنن.در نهایت, این هم لیستی از نکته هایی در مورد این که چه جوری کد بهینه و خوب بنویسیم. شما میتونید این نکته هارو از نوشته بالا استخراج کنید ولی خب این هم یه خلاصه واسه راحتی کار: چه جوری کد جاوا اسکریپت بهینه بنویسیمترتیب پراپرتی های آبجکت: همیشه پراپرتی هایی که به آبجکت ها میدین به یک ترتیب باشه تا از کلاس مخفی و بهینه سازی اون ها به طور اشتراکی استفاده بشه.پراپرتی های داینامیک:  اضافه کردن پراپرتی جدید بعد از ساختن آبجکت باعث اجبار در بروز رسانی کلاس مخفی میشه و تابع هایی که برای کلاس مخفی قبلی بهینه سازی شدن کند میشن. بجاش همه ی پراپرتی هارو تو کانستراکتور ها ست کنید.متودها: کد هایی که یک تابع رو بار ها فراخوانی میکنن سریعتر از کدهایی هستن که تابع های مختلفی رو فقط یک بار فراخوانی میکنن ( بخاطر کش کردن خطی ).آرایه ها: از آرایه های اسپارسی که کلید های افزایشی ندارن ( 0, 1, 2, ...) دوری کنید. آرایه های اسپارسی که کلید های افزایشی ندارن المان های درونی اون ها hash table هست که دسترسی به این المان ها بسیار هزینه بره. همچنین بهتره از آرایه هایی که طول از پیش مشخصی دارن هم دوری کنیم. بهتره هروقت نیاز هست آرایه رو رشد بدیم. و در نهایت: المانی در آرایه رو حذف نکنید. باعث ایجاد ارایه اسپارسی میشه. مقدار های تگ شده: موتور V8 آبجکت ها و عدد هارو با ۳۲ بیت نشون میده. یه بیت استفاده میکنه تا ببینه متغییره آبجکته (flag = 1) و یا اینتجر هست (flag = 0) که SMI - SMall Integer بخاطر ۳۱ بیتی بودنش صدا میشه. اگر متغیر بیشتر از ۳۱ بیت باشه موتور V8 اون (به اصطلاح box میکنه) رو داخل یه دابل یا یه آبجکت میریزه. سعی کنید همیشه عدد های ۳۱ بیتی استفاده کنید تا هزینه سنگین این باکس کردن رو نداشته باشید. پایان :) </description>
                <category>Hassan Gilak</category>
                <author>Hassan Gilak</author>
                <pubDate>Mon, 07 May 2018 16:04:58 +0430</pubDate>
            </item>
                    <item>
                <title>جاوا اسکریپت چه جوری کار میکنه؟ مروری بر engine , runtime و call stack</title>
                <link>https://virgool.io/JavaScript8/how-js-works-runtime-engine-overview-klqtvfvoteor</link>
                <description>سری &quot;جاوا اسکریپت چه جوری کار میکنه؟&quot; بازگردن مقاله های Alexander Zlatkov به زبون خودم هست. هدف از این کار در مرحله ی اول یادگیری خودم و انتشار این مقاله به فارسیه. قرارم بر این نیست که همه کلمات رو به فارسی بگم به این دلیل که اگر خواستید بیشتر جستو جو داشته باشید در مورد کلمات کلیدیش, بتونید راحت تر این کارو انجام بدین.  اهمیت این نوشته برای من محتواش هست نه طرز بیان یا نگارشش. ممنون میشم اگر که هم در محتوا هم در طرز بیان یا نگارش اشکالی هست بیان کنید تا بتونم بهترش کنم. بازگردانی شده از : How JavaScript works: an overview of the engine, the runtime, and the call stackهرچقدر که جاوا اسکریپت داره معروف و معروف تر میشه, تیم های زیادی دارن ازش تو قسمت های مختلف استکشون مثل front-end, back-end, hybrid apps, embedded devices و خیلی مورد های دیگه استفاده میبرن. این نوشته اولین مطلب این سریه و موضوعیتش در مورد فهم عمیق تر جاوا اسکریپت و این که در واقع داره چه جوری کار میکنه هست:‌ ما فکر میکنیم با دونستن اجزای تشکیل دهنده جاوا اسکریپت و تعامل بینشون شما میتونید کد ها و برنامه های بهتری بنویسید. همچنین ما نکاتی که تو ساخت SessionStack, اپلیکیشن سبک جاوا اسکریپتی که باید خیلی چفت و بست دار و سریع باشه تا بتونه رقابت بکنه رو بیان میکنیم. همین طور که از استار های  GitHut.info مشخصه, جاوا اسکریپت بالاتر از همه قرار میگیره تو مورد های مخزن های فعال و تعداد پوش ها به گیتهاب. حتی تو مورد های دیگه هم خیلی عقب نیست از بقیه. (Check out up-to-date GitHub language stats).اگر پروژه ای داره خیلی به جاوا اسکریپت وابسته میشه به این معنی هست که دولوپر ها باید هر چه بیشتر از زبان و همه ی اون چیزی که اکوسیستم براشون فراهم کرده با فهم عمقی تری از اجازی داخلی استفاده ببرن تا بتونم یه برنامه خفن بسازن. اینجور که معلوم هست, دولوپر های زیادی هستن که دارن روزانه از جاوا اسکریپت استفاده میکنن و نمیدونن چه اتفاقاتی داره اون پشت مشت ها میوفته. (من فقط ترجمه کردم. نزنید آدمو)بررسی کوتاه تقریبا همه اسم V8 Engine رو شنیدن یه تصوری ازش دارن, اکثر مردم هم میدونن که جاوا اسکریپت تک ترد هست یا این که داره از صف کال بک ها استفاده میکنه.  تو این نوشته, درمورد همه این موضوعات به طور مفصل صحبت میکنیم و توضیح میدیم که جاوا اسکریپت چه جوری کار میکنه. با دونستن این جزیات, شما میتونید برنامه های بهتر و non-blocking رو بنویسید که به خوبی داره از api های فراهم شده استفاده میکنه. اگر شما تازه کار هستید تو جاوا اسکریپت, این نوشته به شما کمک میکنه که متوجه بشید چرا جاوااسکریپت عجیب تر رفتار میکنه نسبت به زبان های دیگه.و اگر شما یه جاوا اسکریپت دولوپر با تجربه هستید, امیدوار کنندست که این نوشته به شما یه دید جدید در مورد چگونه کار کردن رانتایم جاوا اسکریپت که هر روز دارید باهاش کار میکنید بده.موتور جاوا اسکریپتیه نمونه معروف موتور جاوا اسکریپتی Googles V8 Engine هست. این موتور در دل Chrome و Node.js تعبیه شده. این یه نمایش ساده از این موتور هست که چه ریختیه:این موتور تشکیل شده از دو کامپوننت اصلی هست: Memory Heap - جایی که اختصاص دادن حافظه صورت میگیرهCall Stack - این جا هم فریم های استک نگه داری میشه به هنگام اجرای برنامهرانتایم ای پی آی هایی که تو مرگر هست که تقریبا توسط همه دولوپر های جاوا اسکریپت استفاده شده مثل setTimeout‌, با این حال حتی این api ها توسط موتور جاوا اسکریپت فراهم نشدن . خو پس از کجاش داره میاد ؟ به نظر میرسه که واقعیت در مورد این ها یکم پیچیدست.خب ما موتور جاوا اسکریپت رو داریم ولی در حقیقت چیز های دیگه هم مثلا Web APIs که مرورگر اونها رو فراهم کرده مثل DOM, AJAX و همین تابع setTimeout و خیلی چیزای دیگه. و در کنار این ها event loop و calback queue معروف. پشته اجرایی یا Call Stackجاوا اسکریپت یه زبون تک تردی هست. به این معنی که فقط یه دونه پشته اجرایی داره. پس فقط در لحظه یه کارو میتونه انجام بده. پشته ی اجرایی یه ساختمون داده هست که از دستور هایی که باید اجرا بشن رو تو خودش نگه میداره عملا مشخص میکنه کجای اجرای برنامه هستیم. اگر وارد اجرای یه تابع بشیم اون تابع رو بالای این پشته گذاشتیم و هروقت هم در اون تابع ریترن کردیم از بالای پشته برش میداریم. این همه کاری هست که استک اجرایی میتونه انجام بدهیه مثال ببینیم. کد زیر رو نگاه کنید.function multiply(x, y) {
    return x * y;
}function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}printSquare(5);وقتی موتور جاوا اسکریپت شروع به اجرای این کد میکنه, در اون لحظه شروع پشته اجرایی خالیه. بعد از اون قدما های بعدی به شکل زیر هست:هر ورودی به پشته اجرایی رو میگن Stack Frame. و این دقیقا نحوه ی تولید stack traces رو نشون میده وقتی یه اکسپشنی رخ میده. به طور پایه stack trace وضعیت پشته ی اجرایی رو بیان میکنه در زمانی که اکسپشنی رخ داده. به کد زیر نگاه کنید: function foo() {
    throw new Error(&#039;SessionStack will help you resolve crashes :)&#039;);
}function bar() {
    foo();
}function start() {
    bar();
}start();اگه این کد تو کروم اجرا بشه و اسم فایل اجرایی رو هم بزاریم foo.js استک تریسی مثل عکس پایین باید درست کنه:&quot;منفجر کردن پشته اجرایی&quot; این زمانی اتفاق میوفته که به حد اکثر سایز پشته اجرایی برسیم. که خیلی هم ساده این اتفاق میتونه بیوفته اونم زمانی که داریم از تابع بازگشتی استفاده میکنیم و کدمون درست حسابی تست نکردیم. به این تیکه کد نگاه کنید:function foo() {
    foo();
}foo();وقتی موتور شروع به اجرای این کد میکنه از تابع foo کارشو استارت میزنه. این تابع بازگشتی هست و خودش رو صدا میزنه بدون هیچ شرط اتمامی. پس تو هر مرحله ی اجرا هی تابع foo به پشته اضافه میشه. میشه یه چیزی مثل عکس زیر: بالاخره تعداد فراخوانی تابع داخل پشته اجرایی از حد مجاز میگذره و مرورگر تصمیم یه اروری ایجاد کنه که میتونه این شکلی باشه: اجرای کد ها تو حالت تک تردی خیلی راحته چون دیگه لازم نیست به سناریو های پیچیده ای که تو حالت مالتی ترد پیش میاد فکر کنیم. برای مثال dead locks.ولی خب اجرا برنامه تنها روی یک ترد هم محدودیت های خودش رو داره. وقتی جاوا اسکریپت یه پشته ی اجرای داره وقتی دستور ها کند اجرا میشن چه اتفاقی میوفته؟هم زمانی و چرخه رویداد ها --- Concurrency &amp; the Event Loopچه اتفاقی میوفته وقتی یه فراخوانی از تابع تو پشته داریم و زمان زیادی برای پراسس شدن میخواد؟ برای مثال تصور کنید که شما میخواید یه تبدیل پیچیده روی عکس تو محیط مرورگر انجام بدین.شاید بپرسید خب مشکلش چیه؟ مشکل اینجاست که وقتی پشته اجرایی تابعی برای اجرا داشته باشه مرورگر درواقع هیچکار دیگه ای نمیتونه انجام بده و بلاک میشه. این یعنی مرورگر نمیتونه رندر کنه و کد دیگه ای رو اجرا کنه. یه جا گیر کرده. و خب این مشکل درست میکنه وقتی نیاز به یه UI ترو تمیز داریم. و این تنها مشکل هم نیست. وقتی مرورگر شما شروع به پراسس تعداد زیادی تسک از پشته ی اجرای میکنه , ممکنه برای مدت طولانی دیگه نتونه پاسخ گو باشه. و اکثر مرورگر ها هم این موقع ها یه اروری رو نشون میدن که آیا میخوای این صفحه رو ببندیم ؟حالا این یه تجربه ی کاربری خوب نیست که انتظار میره. درسته ؟خب ما چه جوری میتونیم کد های سنگین رو اجرا بگیریم بدون این که UI رو بلاک کنیم و مرورگر رو بترکونیم؟ راه حل asynchronous callbacks هست. این موضوع تو نوشته بعدی بیشتر توضیح داده میشه. </description>
                <category>Hassan Gilak</category>
                <author>Hassan Gilak</author>
                <pubDate>Sat, 21 Apr 2018 01:35:18 +0430</pubDate>
            </item>
            </channel>
</rss>