آشنایی کامل با Hoisting در Javascript - قسمت 2



visibility  
mode_comment   ۰

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

Hoisting variables

تصویر زیر نشان دهنده چرخه حیات یا Life Cycle تعریف و مقداردهی اولیه به متغیرها در Javascript است:

همونطور که میبینید اولین مرحله، مرحله Declaration و تعریف شدن هست که متغیر a رو با استفاده از var، تعریف کردیم. بعد از اون هم مرحله initialisation یا Assignment هست که در اون مقدار مورد نظرمون رو برای متغیر a قرار میدیم. بعد از اون هست که میتونیم از متغیر a در ادامه برنامه استفاده کنیم. همونطور که قبلا هم اشاره شد، شما میتونین Declaration و Assignment رو بصورت جداگانه انجام بدین و یا اینکه از هر دوی اونا بصورت همزمان استفاده کنید. استفاده همزمان متدوال تر هست. بصورت زیر:

همونطور که قبلا هم گفته شد، قبل از اینکه برنامه ما اجرا بشه، یک مرحله انجام میشه و در اون همه متغیرهایی که Declare شدن به بالای Scope خودشون انتقال داده میشن.

میشه اینطور گفت که تا زمانی که نخوایم مقداری رو به متغیری در مرحله اجرای برنامه نسبت بدیم، خطای مربوط به Undeclared Variable وجود نخواهد داشت. بنابراین زمانی که در مرحله اجرای کد، یک مقدار رو به یک متغیر که قبلا تعریف نشده نسبت میدیم، یک متغیر بصورت ضمنی و خودکار بصورت Global یا سراسری ساخته میشه. پس میشه اینطور گفت که همه متغیرهایی که تعریف نمیشوند، متغیرهای Global یا سراسری هستند.

مثلا کد زیر رو در نظر بگیرید:

زمانی که این کد رو اجرا میکنیم، با اینکه ما اصلا متغیر a رو تعریف نکردیم، باز هم خروجی 100 در مرورگر نمایش داده میشه. این نتیجه به این خاطر هست که متغیر a بصورت ضمنی و خودکار ساخته میشه. پس کد بالا در مرحله اجرای کد، ابتدا خط اول رو اجرا میکنه. اجرا کننده به متغیر a که قبلا تعریفش نکردیم، برمیخوره. پس خودش میاد یک متغیر برای ما میسازه. پس تا اینجای کار که خط اول اجرا میشه، کد بصورت زیر در میاد:

بعد از این مرحله، اجرا کننده به خط بعد میره و میخواد متغیر a رو در Console چاپ کنه. پس به راحتی مقدار 100 رو نمایش میده. بدلیل اینکه متغیر a قبل از Console.log هم تعریف شده و هم مقدار دهی شده است. حالا یک حالت دیگه رو با هم بررسی میکنیم. کد زیر رو در نظر بگیرید:

خب اولین مرحله قبل از اینکه اجرا کننده، برنامه ما رو اجرا کنه، این هست که همه متغیرهای تعریف شده به بالای Scope بروند و Hoist بشن. پس کد بالا قبل از مرحله اجرا بصورت زیر میشه:

خب بعد از این کار مرحله اجرا کد انجام میشه و اجرا کننده به Console.log میرسه. اجرا کننده میخواد مقدار a رو در console چاپ کنه. اما همونطور که میبینید ما هیچ مقداری رو قبل از Console.log برای a قرار ندادیم. پس مقدار undefined یا تعریف نشده در Console چاپ خواهد شد. اجرا کننده بعد از Console.log به خط بعدی میره و در اونجا مقدار 100 رو برای متغیر a قرار میده. از این خط به بعد هر جا از a استفاده کنیم، مقدار a برابر با 100 خواهد بود. اگر یک Console.log دیگه به کد بالا اضافه کنیم، کدها بصورت زیر میشن:

اگر خروجی رو در مرورگر ببینیم، بصورت زیر خواهد بود:

متخصص جاوا اسکریپت
با جاوا اسکریپت جادوگری کنید! آیا می دونید با زبان جاوااسکریپت می تونید، برای فرانت اند و بک اند وبسایت ها برنامه نویسی کنید؟ همینطور اپلیکیشن دسکتاپ و موبایل بسازید؟ اگر دوست داری اینکارها رو انجام بدی و React, ElectronJS, ReactNative, NodeJS,MongoDB و ... رو تو یه دوره یاد بگیری، متخصص جاوااسکریپت سون لرن رو حتما ببین : متخصص جاوا اسکریپت arrow_back

میبینید که در ابتدا undefined و بعد از اون 100 چاپ شده است. خب حالا یک حالت دیگه رو هم در نظر میگیریم. کد زیر رو ببینید:

خب مثل همیشه، مرحله قبل از اجرا شدن کد این هست که متغیر های تعریف شده، به بالای Scope خودشون انتقال داده و Hoist بشن. در کد بالا چون هیچ متغیری تعریف نشده است، پس مرحله اول هیچ چیزی برای Hoist شدن نداریم. خب پس مرحله اجرا شدن کد شروع به کار میکنه. خط اول اجرا میشه و Console.log قصد داره که مقدار a رو در console نمایش بده. اما ما قبل از console.log نه a رو تعریف کردیم و نه اون رو مقدار دهی کردیم، پس در اینجا با یک ارور مواجه میشیم:

more  بیشتر بخوانید : ترفندهای پیشرفته jQuery (قسمت 19)

زمانی که در javascript با یک ارور مواجه میشیم، روند اجرای برنامه قطع میشه و اجرا کننده به خطهای بعد نمیره. میتونیم برای اینکه بهتر متوجه بشیم، این دستور رو در try catch قرار بدیم تا ببینیم در خط بعدی چه اتفاقی خواهد افتاد. برای اینکار بصورت زیر عمل میکنیم:

میبینید که خط اول رو درون بلاک try قرار دادم و درون بلاک catch با استفاده از e به ارور دسترسی خواهم داشت و میتونم اون رو در Console چاپ کنم. تنها فرقی که این کد با کد بالا داره اینه که اجرا کننده قادر هست به خطهای بعدی بره و وجود ارور جلوی روند اجرای برنامه رو نخواهد گرفت. خب پس دیدیم که a تعریف نشده بود. حالا اجرا کننده به خط بعد میره و با کد a = 100 روبرو میشه. اجرا کننده با خودش میگه قبلا متغیری با نام a بصورت واضح یا explicit تعریف نشده. پس خود اجرا کننده یک متغیر بنام a رو بصورت ضمنی یا implicit در Scope سراسری یا Global میسازه. پس کد بصورت زیر خواهد شد:

پس حالا اگر یک Console.log دیگه قرار بدیم و بخوایم مقدار a رو چاپ کنیم، مقدار 100 در خروجی چاپ خواهد شد.

حالا برای فهم بیشتر مثال دیگری رو نیز در نظر میگیریم. کد زیر رو ببینید:

خب در اینجا هم مثل قبل، مرحله Hoist کردن در ابتدا و قبل از اجرا شدن انجام میشه. همونطور که میبینید فقط متغیر b که درون تابع hoist وجود داره، تعریف شده است. پس در این مرحله فقط این متغیر به بالای Scope خودش که تابع hoist هست، انتقال داده میشه. کدهای بالا بعد از این مرحله بصورت زیر خواهند شد:

خب حالا مرحله hoisting به پایان میرسه و وارد مرحله اجرا میشیم. اجرا کننده شروع به اجرای خط به خط میکنه. در ابتدا از تعریف تابع hoist رد میشه چون هنوز اون رو صدا نزدیم و call نکردیم. اجرا کننده مستقیما تا خط 7 میره و در اونجا تابع hoist صدا زده میشه. خب با اینکار اجرا کننده وارد تابع hoist میشه و کدهای درون اون رو اجرا میکنه. در ابتدا به عبارت a = 20 میرسیم و میبینیم که هیچ کجا متغیر a رو تعریف نکردیم. پس اجرا کننده یک متغیر بصورت ضمنی در حوزه سراسری به وجود میاره. در خط بعد چون متغیر b قبلا تعریف شده، متغیر جدیدی ساخته نمیشه و فقط مقدار 100 به اون نسبت داده میشه. پس تا اینجا کد بصورت زیر میشه:

اجرای کدهای تابع به اتمام میرسه و میریم سراغ Console.log ها و اونا رو اجرا میکنیم. چون a متغیر سراسری هست، به مقدار اون دسترسی داریم ولی چون b درون تابع تعریف شده و متغیر محلی یا local هست، به اون دسترسی نداریم و با ارور مواجه خواهیم شد. پس خروجی بصورت زیر میشه:

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

امیدوارم از این مطلب خوشتون اومده باشه.

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

یا علی

comment دیدگاه کاربران
ارسال نظرات

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