بررسی کامل نحوه کارکرد جاوا اسکریپت

آموزش درک مفاهیم جاوا اسکریپت

در این مقاله قصد دارم با بررسی دقیق جاوا اسکریپت و بررسی مفاهیمی همچون call stack, event loop, task queue و… به کارکرد جاوا اسکریپت و موتور آن در مرورگرها و node بپردازم، با من همراه باشید.

بیایید قبل از اینکه درباره موتور جاوا اسکریپت و اینکه چطور هر بخش با بخش دیگر کار می‌کند صحبت کنیم، چند مفهوم ساده اما پایه‌ای را بررسی کنیم.

بررسی اجمالی جاوا اسکریپت

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

ویژگی دیگر جاوا اسکریپت daynamic type بودن آن است. به این معنی که در جاوا اسکریپت بر خلاف زبان‌هایی مثل c و ++c نیاز نیست به محض تعریف متغییر نوع آن را نیز مشخص کنید. موتور جاوا اسکریپت با توجه به محتوای(value‌) یک متغییر درباره نوع آن قضاوت می‌کند. به همین خاطر در جاوا اسکریپت وقتی یک متغییر را با var,let یا const تعریف می‌کنید، میتوانید هر مقداری(number, string, Boolean,obj,arr… ) به آن نسبت دهید.

اگر میخواهید خیلی مختصر اما کامل تفاوت روش‌های مختلف تعریف متغییر در جاوا اسکریپت را بررسی کنید، مقاله بررسی تفاوت let, var و const در برنامه نویسی جاوا اسکریپت را از دست ندهید.

دوره های اموزشی برنامه نویسی

همین نبود یک سیستم تعیین نوع، باعث میشود کارایی(performance‌) جاوا اسکریپت نسبت به زبان‌هایی مثل c و c++ پایین‌تر باشد.

همین حالا دوره رایگان آموزش جاوا اسکریپت مقدماتی را دانلود کنید.

تاریخچه جاوا اسکریپت

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

در ابتدای پیدایش صفحات وب، این صفحات استاتیک بودند. در واقع کارکردی که صفحات وب در ابتدا داشتند مشابه کارکرد مجلات بود و این صفحات هیچ تعاملی با کاربر نداشتند.

در سال ۱۹۹۵، Brendan Eich زبان جدیدی معرفی کرد به اسم جاوا اسکریپت. این زبان در مرورگرهای Netscape‌ استفاده میشد. نکته قابل توجه اینکه، طراحی زبان جاوا اسکریپت صرفا ۱۰ روز زمان برد!

همانطور که حدس میزنید نمیشود از خروجی یک تلاش ۱۰ روزه، انتظار یک شاهکار داشت! اما اگر بخواهیم منصف باشیم، همان خروجی اولیه برای ۱۰ روز تلاش، واقعا فوق‌العاده بود( نه لزوما بی‌نقص).

جاوا اسکرپت با هدف بالا بردن performance‌ طراحی نشده بود، بلکه هدف طراحی جاوااسکریپت صرفا دسترسی به DOM در مرورگر و ایجاد تعامل با کاربر بود. از آنجاییکه کم کم همه مرورگرها میخواستند با جاوا اسکریپت سازگاری پیدا کنند، باید استانداردهایی برای این زبان تعریف میشد.

Ecma International سازمانی است که استانداردهای حوزه تکنولوژی را تبیین میکند. به استانداردی که این سازمان برای زبان‌های اسکریپتی و به طور خاص جاوا اسکریپت تعیین کرده است، EcmaScript می‌گویند.

آناتومی موتور JS

استاندارد اکما اسکریپت درباره ویژگی‌هایی که جاوا اسکریپت باید داشته باشد تا خروجی آن در تمام مرورگرها یکسان باشد، صحبت می‌کند. اما درباره اینکه موتور جاوا اسکریپت چطور باید کدهای جاوا اسکریپت را اجرا کند، استانداردی تعیین نشده است. به همین دلیل موتور جاوا اسکریپت در هر مرورگر متفاوت از مرورگرهای دیگر است.

پس تا اینجا متوجه شدیم که هر مرورگر یک موتور جاوا اسکریپت دارد. با اینکه ساختار موتور جاوا اسکریپت هر مرورگر متفاوت است اما اکثرا خروجی کد و کارکرد جاوا اسکریپت در مرورگرها یکسان است. چرا میگویم اکثرا؟ چون زبان جاوا اسکریپت دائما در حال بروز رسانی است اما تمام مرورگرها موتور خود را با سرعت بروزرسانی جاوا اسکریپت، بروز نمی‌کنند.

مرورگر Netscape‌ از موتور جاوا اسکریپت spiderMonkey استفاده می‌کرد. spiderMonkey یک مفسر ابتدایی بود که سرعت پایینی داشت اما درست کار میکرد.

نحوه کارکرد جاوا اسکریپت

همانطور که در عکس بالا میتوانید ببینید، کار اولین موتور جاوا اسکریپت این بود که کد جاوا اسکریپت را دریافت میکرد و در نهایت آن را به کد ماشین تبدیل می‌کرد(کد قابل فهم برای سخت‌افزار).

در این بین کامپایلر پایه(baseline) وظیفه داشت که کد را در سریعترین زمان ممکن کامپایل کرده و یک بایت کد که تقریبا بهینه شده‌است را تولید کند. از آنجایی که مفسر قرار است با این بایت کد غیر بهینه کار کند، سرعت دریافت خروجی پایین بود.

  • . شایان ذکر است بعدها از spiderMoney به عنوان بخشی از موتور بزرگ و بهینه‌ی مرورگرهای فایرفاکس استفاده شد.

با این موتور جاوا اسکریپت توانایی ساخت یک برنامه تحت وب پویا که تعامل خوبی با کاربر داشته باشد، عملا غیر ممکن بود. پس به ناچار باید به دنبال راهکار بهتری میبودند.

مرورگر گوگل کروم از همان روزهای پیداش جاوا اسکریپت از موتور V8 استفاده میکرد. در ابتدا برای بهبود عملکرد، این موتور را با دو Pipeline‌ طراحی و از آن استفاده میکردند. مشابه تصویر زیر:

جاوا اسکریپت چطور کار می کند

نسخه موتور v8 در سال ۲۰۱۰ ، از دو بخش اصلی تشکیل شده بود که کاراهای سنگین بر عهده آن دو بخش بود:

  1. اولین بخش full-codegen بود که وظیفه داشت کد بهینه نشده را در سریعترین زمان ممکن برای راه‌اندازی برنامه، تولید کند.
  2. همانطور که full-codegen با تولید سریع کدهای غیر بهینه، برنامه را اجرا میکرد، این کامپایلر وظیفه داشت کد اصلی را بهینه کند و کدهای بهینه را با کدهای غیر بهینه که کامپایلر اصلی تولید کرده‌است، جایگزین کند.

با رویکردی که موتور v8 داشت، عملکرد برنامه بهتر و بهتر میشد و رضایت نسبی کاربران فراهم میشد.

هر چند این رویکرد نیز به دلیل مصرف زیاد حافظه و پردازنده، هزینه‌های زیادی داشت که برنامه نویسان را مجبور میکرد به دنبال رویکرد بهتری باشند.

جالب است بدانید این نسخه از v8 فاقد هرگونه مفسر است و از کامپایلر مدل JIT (just-in-time) بهره میبرد. این نوع مدل کامپایلر یک مدل تلفیقی است که ابتدا کد را به زبان ماشین کامپایل میکند و بعد آن را بهینه میکند.

بهینه سازی جاوا اسـکریپت

قبل از اینکه کد جاوا اسکریپت به مفسر یا کامپایلر فرستاده شود، ابتدا باید در یک درخت ترکیب نحوی(abstract syntax tree‌) منتقل(parse‌) شود.

توجه کنید وقتی یک برنامه جاوا اسکریپت را اجرا میکنیم نیازی نیست در همان ابتدا کل برنامه را به درخت ترکیب نحوی منتقل کنید. فرض کنید یک function داریم که در صورتیکه کاربر بر روی یک دکمه کلیک کند، آن تابع فرخوانی میشود. در چنین مواردی میتوانیم کد را بعدا و در موقع نیاز به درخت منتقل کنیم.

به همین منظور موتور جاوا اسکریپت باید کدهایی که در همان ابتدا ضروری هستند را شناسایی و فورا به کد ماشین تبدیل کند. این بهترین استراتژی برای اجرای سریع کدهای جاوا اسکریپت است.

 

در ضمن، موتور جاوا اسکریپت میتواند در کدهای در حال اجرا جستجو کند و کدی که کندتر اجرا میشود را پیدا کند. به همچین کدی Hot‌ کد میگویند. به این دلیل که ممکن است از cpu‌ بیش از اندازه کار بکشد و باعث داغ شدن آن شود(چه بسا cpu را بسوزاند!). چنین کدی باید بیشتر بهینه شود و با کد ماشین بهینه شده جایگزین شود.

در نهایت برای بهبود موتور v8 کارهای دیگری نیز انجام شد که Paul Ryan‌ در این مقاله به تفصیل درباره آن‌ها صحبت کرده است.

تیم توسعه دهنده موتور v8 با در نظر گرفتن موارد گفته شده، نسخه جدیدی از v8 را ایجاد کردند که در سال ۲۰۱۷ منتشر شد و در دسترس عموم قرار گرفت.

جاوا اسـکریپت چطور کار می‌کند؟

همانطور که در تصویر بالا میبینید، تیم v8‌ یک pipeline جدید برای مفسر Ignition تعریف کرده است. این pipeline وظیفه دارد با کمک یک کامپایلر از کد اصلی (source code‌) بایت کد تولید کند و با استفاده از یک مفسر بایت کد را تفسیر کند.

کامپایلر بهینه‌ساز TurboFan میتواند بایت کدها را، زمانی که برنامه در حال اجرا است، بهینه کرده و درنهایت یک کد ماشین بسیار بهینه تولید کرده و آن را با کد قبلی جایگزین کند.

در واقع این کامپایلر توانایی دارد اطلاعات برنامه را از Ignition‌ دریافت کرده و کد Hot را پیدا و آن را بهینه کند.

عملکرد سایر موتورهای جاوا اسکریپت چگونه است؟

تا به اینجا یک دید کلی از موتور جاوا اسکریپت v8 را بررسی کردیم و با کارکرد جاوا اسکریپت تا حدی آشنا شدیم. بقیه موتورهای جاوا اسکریپت ( spiderMonkey در مرورگر فایرفاکس، Chakra در مرورگر اینترنت اکسپلورر و …)  نیز تقریبا ساز وکار مشابهی دارند.

بعضی از این موتورهای جاوا اسکریپت ممکن است پیچیده‌تر به‌نظر برسند زیرا دارای چندین کامپایلر و بهینه ساز هستند اما در نهایت رویکرد کلی‌شان به عملکرد v8 نزدیک است.

شاید فکر کنید علت معروفیت v8 این است که توسط گوگل توسعه داده‌شده است. هرچند این نکته‌ی مهمی است اما مهم‌تر از آن این است که v8 دائما در حال تکامل است.

کارکرد جاوا اسکریپت در زمان اجرا

برنامه نویس‌های زیادی در سرتاسر دنیا، با کمک جاوا اسکریپت به توسعه وب (back-end و front-end‌) می‌پردازند. هرچند فهم جاوا اسکریپت کار خیلی سختی نیست، اما اگر بخواهم با شما صادق باشم: فهم دقیق جاوا اسکریپت، مثل آب خوردن هم نیست!

برخلاف سایر زبان‌های برنامه نویسی، جاوا اسکریپت در زمان اجرا(run-time) صرفا از یک thread‌ استفاده می‌کند. مفهوم جمله قبل این است که: در هر لحظه صرفا یک تکه از کد اجرا میشود و به عبارت دیگر اجرای همزمان چند قطعه کد امکان پذیر نیست! به همین خاطر در زمان اجرای یک قطعه کد، تا وقتی کد به صورت کامل اجرا نشده، کدهای بعدی اجرا نمی‌شوند ( در واقع کدهای بعدی بلاک میشوند). به همین دلیل است که گاهی حین استفاده از گوگل کروم صفحه زیر را مشاهده میکنید:

آموزش مفاهیم زبان برنامه نویسی جاوا اسـکریپت

وقتی شما یک وب سایت را در مرورگر جستجو میکنید، یک thread جاوا اسکریپت ایجاد میشود. این ترد وظیفه دارد به تمام اتفاقات رسیدگی کند. چه اتفاقاتی؟ مثلا اسکرول کردن در صفحه، عکس العمل نشان دادن به اتفاقاتی که در DOM رخ می‌دهد (مثل کلیک کردن بر روی یک دکمه) و اتفاقاتی از این قبیل.

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

برای اینکه صحت صحبت‌های من را بسنجید، میتوانید در ابتدای کد خود یک حلقه بی‌نهایت بنویسید و وضعیت اجرای کدهای بعد از این حلقه را بسنجید.

while(true){}

البته جای شکرش باقیست. به لطف مرورگرهای امروزی، هر tab در مروگر یک ترد مخصوص خودش را دارد. به همین خاطر است که در یک مرورگر میتوانید چندین tab‌ باز کنید و به کارهای مختلفتان رسیدگی کنید.

پس تمام توضیحات قبلی درباره بلاک کردن کدها، تا زمان اتمام اجرای کد فعلی مربوط به کدها و eventهای یک tab است و اجرای همزمان چند رخداد در tabهای مختلف، منافاتی با هم ندارد.

برای فهم بهتر نحوه اجرای کدهای جاوا اسکریپت، باید به درک عمیق و درستی از javascript runtime برسیم. پس اجازه میخواهم توضیحاتم را با یک کد ساده ادامه دهم:

 

function baz() {
	  console.log( 'Hello from baz' );
	}
	

	function bar() {
	  baz();
	}
	

	function foo() {
	  bar();
	}
	

	foo();

 

در کد بالا سه تابع داریم که هر یک دیگری را فراخوانی کرده است. میخواهیم ببنیم زمانی که تابع foo را اجرا میکنیم، موتور جاوا اسکریپت در پشت صحنه چطور عمل میکند؟

زمانیکه تابع foo را فراخوانی میکنیم، رشته ای از فراخوانی‌ها اتفاق میوفتد. تابع foo تابع bar را فراخوانی میکند و تابع bar تابع Baz را فراخوانی میکند. در نهایت baz عبارتی را در کنسول چاپ میکند. حالا جزئیات این اتفاقات را با تصاویری که در ادامه آمده بهتر متوجه میشویم. پس با من همراه باشید:

جاوا اسـکریپت چطور کار میکند

مثل هر زبان برنامه نویسی دیگر، جاوا اسکریپت runtime از یک stack و یک heap تشکیل شده است. Heap‌ یک حافظه خالی است که میتوانید اطلاعات را به صورت رندوم(بدون ترتیب خاصی) در آن ذخیره کنید. Javascript runtime این حافظه را مدیریت میکند و garbeg collector وظیفه پاکسازی هیپ، از داده‌های غیر ضروری را دارد. بیش از این به جزئیات هیپ نمیپردازم اما اگر به جزئیات علاقه دارید، در این مقاله میتوانید جواب سوالاتتان را پیدا کنید.

در ادامه قصد داریم بیشتر درباره‌ی ساختار استک صحبت کنیم. ساختمان داده استک LIFO است. یعنی دیتایی که آخر از همه وارد استک شده است، زودتر از همه خارج میشود(last in, first out‌). باید بدانید در هر لحظه از اجرای کد، execution context‌ مربوط به آن کد در استک push میشود. ( اگر نمیدانید execution context‌ چیست در کامنت‌ها اطلاع دهید). همانطور که گفتم در برنامه ما وقتی برنامه در memory قرار میگیرد، اجرای برنامه با فرخوانی تابع foo شروع میشود.

پس اولین ورودی استک تابع foo است. چون تابع foo تابع bar را فراخوانی میکند، پس دومین ورودی استک تابع bar است. قبلا باقی مراحل اجرا برنامه را توضیح داده‌ام اما در تصویر زیر میتوانید به صورت گرافیکی اتفاقاتی که رخ میدهد را مشاهده کنید.

توجه کنید تا زمانی که تابع در حال اجرا، خروجی را return نکند، اجرای آن تمام نمیشود. پس به محض return کردن خروجی، اجرای تابع تمام شده و از استک pop میشود.

نحوه کارکرد جاوا اسکریپت

به هر ورودی استک، stack frame میگویند. هر stack frame شامل اطلاعاتی از فراخوانی تابع است. آرگومان‌های تابع فراخوانی شده، محل تابع، آدرس محلی که خروجی تابع به آن‌جا فرستاده میشود، چند مثال از اطلاعات stack frame است. در تصویر زیر که با کمک Devtools‌ مرورگر کروم فراهم شده است، بهتر میتوانید این اطلاعات را مشاهده کنید.

آموزش جاوااسکریپت

برای اینکه بتوانید به اطلاعات بالا دسترسی پیدا کنید باید در کنار خط کدی که میخواهید breakpoint‌ قرار دهید. در این صورت بعد از اجرا میتوانید در قسمت راست اطلاعات استک را ببینید.

آموزش کارکرد js

اگر کد ما به خطا بربخورد چه اتفاقی برای استک رخ میدهد؟

در این صورت جاوا اسکریپت یک stack trace ایجاد میکند که صرفا بیانگر روند اجرای کد تا رسیدن به خطا است. با کمک این ابزار به خوبی میتوانید خطاهای کدتان را برطرف کنید. برای اینکه بهتر متوجه موضوع شوید، به مثال زیر توجه کنید:

function baz(){
	   throw new Error('Something went wrong.');
	}
	

	function bar() {
	   baz(); 
	}
	

	function foo() {
	   bar(); 
	}
	

	foo();

در مثال بالا در تابع baz یک error را برمیگردانیم. به همین خاطر وقتی جاوا اسکریپت با خطا مواجه میشود، Stack trace‌ زیر را در کنسول چاپ میکند تا نشان دهد در کجا چه خطایی رخ داده است.

نحوه کارکرد جاوا اسکریپت

همانطور که قبلا گفتم جاوااسکریپت single thread است، به همین خاطر است که تنها یک heap و یک stack‌ برای هر برنامه دارد. بنابراین اگر برنامه دیگری بخواهد اجرا شود، باید منتظر باشد که کد قبلی تمام شود. (هر چند این موضوع را قبلا گفته‌ام اما برای یادآوری و جا افتادن موضوع باید اینجا نیز بیان میشد.)

حالا از شما اجازه میخواهم تا با هم یک سناریو را بررسی کنیم. فرض کنید در یک صفحه وب هستید و میخواهید در سایتی ثبت نام کنید. برای ایجاد پروفایلتان نیاز است تا عکس کاربریتان را آپلود کنید. طبق گفته‌های قبلیمان تا زمانی که عکس به طور کامل آپلود شود، مرورگر فریز میشود و شما نمیتوانید عملیات دیگری انجام دهید. آیا در واقعیت همچین اتفاقی میوفتد؟ خیر. ( اگر این اتفاق میوفتاد تجربه کاربری(ux) با خط بزرگی مواجه میشد)

چه چیزی ux را از این خطر بزرگ نجات میدهد؟ همانطور که گفتیم در هر مرورگر یک موتور جاوا اسکریپت تعبیه شده است که وظیفه اجرای تمام کدهای جاوا اسکریپت داخل وبسایت‌ها را برعهده دارد. اما کلید طلایی جای دیگریست. موتور جاوا اسکریپت تنها نیست! به تصویر زیر نگاه کنید تا مطلب بهتر برایتان جا بیوفتد:

کارکرد جاوا اسکریپت

شاید فکر کنید اوضاع بد است و مطلب حسابی پیچیده شده. اما اصلا نترسید، در ادامه با یکی از قشنگترین و منطقی‌ترین هارمونی‌های دنیای وب آشنا میشوید که نه تنها سخت نیست بلکه خیلی شیرین هم هست. همانطور که در تصویر هم می‌بینید Javascrpt runtime‌ شامل دو بخش دیگر هم هست. یکی event loop و دیگری callback queue .

قبل از اینکه درباره این دو بخش توضیحات بیشتری بدهم،‌لازم است بدانید مرورگرها جدا از موتور جاوا اسکریپت، شامل چند برنامه دیگر هم هستند. این برنامه‌ها امکان ارسال درخواست‌های http‌، پاسخ دادن به رخدادهای DOM ، ایجاد تاخیر در برنامه با کمک setTimeout و setInternal ، ذخیره کردن اطلاعات و کارهای دیگری را فراهم می‌کنند. با کمک همین ویژگی‌ها میتوانیم یک وبسایت بی‌عیب و نقص را پیاده‌‌سازی کنیم.

 

برگردیم سر موضوع اصلی، مرورگر با کمک event loop ، callback queue و موتور جاوا اسکریپت سعی میکند به تمام eventها ( چه آن‌های که مربوط به خود جاوا اسکریپت است چه آن‌هایی که با کمک ویژگی‌هایی که در بالا نام بردم، پیاده سازی شده‌اند) طوری رسیدگی کند که در اجرای برنامه توقفی ایجاد نشود و کاربر تجربه خوبی حین استفاده از وبسایت داشته باشد.

به برنامه‌هایی که این امکان را برای ما فراهم میکنند web api‌ میگویند. این برنامه‌ها غالبا با زبان‌های سطح پایین مثل c++ نوشته شده‌اند و به صورت api در اختیار برنامه نویس‌ها قرار گرفته‌اند. این api ها asynchronous هستند. به همین خاطر این امکان را برای برنامه نویس‌ها فراهم میکنند که عملیاتی را در پشت صحنه انجام دهند و نتیجه را برگردانند بدون اینکه کدی بلاک شود.

در واقع چتر نجات جاوا اسکریپت برای داشتن یک برنامه خوب بدون فریز کردن صفحات وب، این Api ها هستند. زمانیکه این apiها در حال انجام عملیاتی در پشت صحنه هستند، میتوانیم با نوشتن یک callback function مسئولیت انجام کاری را به main thread‌ بسپاریم.

 

پس یکبار دیگر سناریو را با وجود api ها بررسی میکنیم. وقتی شما تابع را فراخوانی می‌کنید، آن تابع در استک push میشود. اگر تابع ما Apiای را فراخوانی کرده باشد، اجرای آن برعهده api‌ گذاشته میشود. در واقع در تردی خارج از ترد اصلی اجرا میشود. همین نکته باعث میشود برنامه بلاک نشود و خطوط بعدی اجرا شوند.

وقتی تابع به خط return‌ میرسد و درواقع اجرای تابع تمام میشود، تابع از استک pop میشود و ترد اصلی به سراغ اجرای کد بعدی در استک میرود. در همین حال api در پشت صحنه و خارج ترد اصلی کارش را انجام میدهد و به خاطر دارد که خروجی‌اش را باید به کجا برگرداند.

برای اینکه مطالب بهتر جا بیوفتد به این مثال توجه کنید. میخواهیم ببینیم در برنامه پایین که از setTimeout Web API استفاده کرده‌ایم، اجرای برنامه مرحله به مرحله چطور اتفاق میوفتد. setTimeout این امکان را به ما میدهد که یک کد را با تاخیر اجرا کنیم. سینکس آن به این صورت است:

setTimeout(callbackFunction, timeInMilliseconds);

callbackfunction تابعی است که بعد از گذشت چند ثانیه(میزان زمان در timeInMilliseconds مشخص شده است) اجرا میشود.


function printHello() {
	    console.log('Hello from baz');
	}
	

	function baz() {
	    setTimeout(printHello, 3000);
	}
	

	function bar() {
	    baz();
	}
	

	function foo() {
	    bar();
	}
	

	foo();

تنها تغییری که در برنامه ایجاد کرده‌ایم در تابع baz است. در این تابع بجای چاپ خروجی در کنسول، SetTimeout‌ را فراخوانی کرده‌ایم که بعد از ۳ ثانیه تابع prinHello را اجرا میکند. در تصویر زیر به اتفاقاتی که در پشت صحنه و در استک میوفتد دقت کنید.

بررسی نحوه کارکرد js

بعد از فراخوانی تابع foo این تابع در استک push میشود. چون در بدنه این تابع، تابع bar فراخوانی شده است، برای اجرای تابع foo‌ باید تابع bar را نیز فراخوانی کنیم. پس bar‌ نیز بر روی استک قرار میگیرد. به همین دلیل تابع baz نیز در استک قرار میگیرد. در این مرحله و برای اجرای تابع baz باید setTimeout را اجرا کنیم. اما چون باید یک تاخیر ۳ ثانیه‌ای بیوفتد و بعد اجرا شود،‌پس از استک pop میشود و در web apis قرار میگیرد.

حالا تابع‌های baz‌ و bar‌ و foo به ترتیب اجرا میشوند و از استک pop  میشوند. در همین حسن ۳ ثانیه در حال گذر است. بعد از اتمام ۳ ثانیه تابع printHello از web apis‌به callback queue منتقل میشود. وظیفه  callback queue این است که چک کند آیا استک خالی است یا نه. اگر استک خالی بود تابع printHello را در استک push میکند تا اجرا شود و از استک pop‌ شود.

کلام پایانی

در این مقاله تمام سعی‌ام بر این بود که کارکرد جاوا اسکریپت را به صورت مفصل و با تشریح چندین مثال و نمودار بررسی کنم. امیدوارم که این مقاله در فهم هر چه بهتر کارکرد جاوا اسکریپت به شما کمک کرده باشد.

اگر سوال یا نظری درباره جاوا اسکریپت،‌ برنامه نویسی آن یا بخش‌های مختلفش دارید، با من و سایر خوانندگان این مقاله در میان بگذارید. حتما به سوالات شما پاسخ خواهیم داد.

برای اطلاع از آخرین تخفیف ها و دوره‌های آموزشی و مطالب مختلف به روز ما، در کانال تلگرام ‌چ‌ یاب عضو شوید.

منابع:

مهندس کامپیوتر👩‍💻 | علاقه‌مند به برنامه نویسی💻| دیجیتال مارکتینگ📱| بسکتبال🏀| تولید محتوا🖋