در این مقاله چه میآموزید؟
- Hoisting چیست؟
- چرا Hoisting به وجود آمده است؟
- Execution Context چه نقشی در Hoisting دارد؟
- Hoisting متغیرها
- Hoisting توابع
- Temporal Dead Zone یا TDZ
- Behind the Scenes موتور JavaScript
- اشتباهات رایج توسعهدهندگان
- بهترین روشهای استفاده
- مثالهای واقعی پروژه
مقدمه
تقریباً همه برنامهنویسان جاوااسکریپت حداقل یکبار با خطاهایی روبهرو شدهاند که علت آنها در نگاه اول کاملاً عجیب به نظر میرسد. متغیری قبل از تعریف مقدار دارد یا تابعی قبل از محل تعریف خود بدون مشکل اجرا میشود. دلیل اصلی این رفتار مفهومی به نام JavaScript Hoisting است.
بسیاری تصور میکنند Hoisting به معنی جابهجا شدن کدها در حافظه است، اما واقعیت چیز دیگری است. موتور JavaScript قبل از اجرای برنامه، مرحلهای برای ساخت Execution Context انجام میدهد و همین فرآیند باعث رفتارهایی میشود که آن را Hoisting مینامیم.
اگر مفهوم Hoisting را به خوبی درک کنید، فهم موضوعاتی مانند Scope، Closures، Execution Context و حتی Debug کردن کدهای پیچیده بسیار سادهتر خواهد شد. به همین دلیل تقریباً تمام مصاحبههای شغلی JavaScript درباره این موضوع سؤال دارند.
JavaScript Hoisting چیست؟
Hoisting فرآیندی است که در مرحله ساخت Execution Context انجام میشود. در این مرحله موتور JavaScript قبل از اجرای خطبهخط برنامه، تمام Declarationها را بررسی میکند تا فضای لازم برای متغیرها و توابع را ایجاد کند.
به همین دلیل ممکن است بتوانید بعضی متغیرها یا توابع را قبل از محل تعریفشان استفاده کنید. البته این رفتار برای همه انواع Declaration یکسان نیست و دقیقاً به نوع تعریف متغیر یا تابع بستگی دارد.
نکته
NOTEچرا Hoisting در JavaScript وجود دارد؟
جاوااسکریپت قبل از اجرای برنامه ابتدا محیط اجرای خود را آماده میکند. این آمادهسازی باعث میشود حافظه موردنیاز برای متغیرها، توابع و Scopeها از قبل مشخص شود و موتور بتواند اجرای کد را سریعتر مدیریت کند.
در نتیجه هنگام رسیدن به هر دستور، موتور دیگر نیازی به ایجاد فضای جدید برای Declarationها ندارد و تنها مقداردهی یا اجرای آنها انجام میشود. همین موضوع یکی از دلایل اصلی وجود Hoisting محسوب میشود.
Creation Phase و Execution Phase
هر Execution Context در JavaScript دو مرحله اصلی دارد. ابتدا Creation Phase اجرا میشود و سپس Execution Phase آغاز خواهد شد. تقریباً تمام رفتارهای Hoisting در مرحله اول اتفاق میافتد.
| مرحله | عملیات |
|---|---|
| Creation Phase | ساخت Scope، ثبت متغیرها و توابع، ایجاد فضای حافظه |
| Execution Phase | اجرای خط به خط برنامه و مقداردهی متغیرها |
Hoisting متغیرهای var
متغیرهایی که با var تعریف میشوند در مرحله Creation Phase مقدار اولیه undefined دریافت میکنند. بنابراین قبل از رسیدن به خط تعریف نیز وجود دارند، اما هنوز مقدار واقعی آنها تعیین نشده است.
مثال ساده
در مثال زیر مشاهده میکنید که متغیر قبل از تعریف قابل دسترسی است، اما مقدار آن undefined خواهد بود.
console.log(username);
var username = "Ali";
console.log(username);
خروجی
خروجی کد
CODE OUTPUTundefined
Ali
در مرحله Creation حافظهای برای username ایجاد میشود و مقدار اولیه آن undefined است. سپس هنگام اجرای خط سوم مقدار واقعی جایگزین خواهد شد.
Best Practice
BEST PRACTICEBehind the Scenes؛ پشت صحنه Hoisting
اگر موتور JavaScript را به صورت ذهنی شبیهسازی کنیم، قبل از اجرای کد بالا ابتدا Declarationها جمعآوری میشوند. سپس برای متغیر username حافظهای با مقدار undefined ایجاد میشود و در نهایت Execution آغاز خواهد شد.
| مرحله | حافظه | مقدار |
|---|---|---|
| Creation | username | undefined |
| Execution | username | “Ali” |
Hoisting متغیرهای let و const
بسیاری از توسعهدهندگان تصور میکنند متغیرهای let و const اصلاً Hoist نمیشوند، اما این تصور کاملاً نادرست است. این متغیرها نیز در مرحله Creation Phase ثبت میشوند، اما تا زمان رسیدن برنامه به خط تعریف، قابل دسترسی نیستند.
این بازه زمانی با نام Temporal Dead Zone (TDZ) شناخته میشود. هرگونه دسترسی به متغیر در این محدوده باعث ایجاد خطای ReferenceError خواهد شد و برنامه متوقف میشود.
مثال استفاده از let
در مثال زیر مشاهده میکنید که متغیر وجود دارد اما هنوز مقداردهی نشده و داخل Temporal Dead Zone قرار دارد.
console.log(username);
let username = "Ali";
خروجی
خروجی کد
CODE OUTPUTReferenceError:
Cannot access ‘username’ before initialization
اگرچه موتور JavaScript حافظه مربوط به متغیر را از قبل ایجاد کرده است، اما تا زمان اجرای دستور let اجازه دسترسی به آن را نمیدهد.
هشدار
WARNING
آیا Class نیز Hoist میشود؟
کلاسها نیز مانند let و const در مرحله Creation Phase ثبت میشوند، اما تا قبل از اجرای دستور class داخل Temporal Dead Zone قرار دارند. به همین دلیل استفاده از کلاس قبل از تعریف باعث ایجاد ReferenceError خواهد شد.
بسیاری از توسعهدهندگان تصور میکنند Class مانند Function Declaration رفتار میکند، اما در واقع رفتار آن بسیار شبیه let و const است.
const user = new User();
class User {
constructor() {
this.name = "Ali";
}
}
خروجی
خروجی کد
CODE OUTPUTReferenceError:
Cannot access ‘User’ before initialization
هشدار
WARNINGTemporal Dead Zone (TDZ) چیست؟
Temporal Dead Zone یا به اختصار TDZ بازهای است که از ابتدای Scope آغاز میشود و تا محل اجرای دستور let یا const ادامه دارد. در این بازه متغیر ایجاد شده اما هنوز مقدار اولیه دریافت نکرده است.
هدف اصلی TDZ جلوگیری از استفاده تصادفی از متغیرها قبل از مقداردهی است. این ویژگی باعث شده بسیاری از خطاهای رایج که در زمان استفاده از var رخ میداد، دیگر به وجود نیاید.
| نوع تعریف | Hoisting | قبل از تعریف |
|---|---|---|
| var | بله | undefined |
| let | بله | ReferenceError |
| const | بله | ReferenceError |
Best Practice
BEST PRACTICEHoisting داخل Block Scope
یکی از تفاوتهای مهم var با let و const مربوط به محدوده دسترسی آنها است. متغیرهای var فقط دارای Function Scope هستند، اما let و const برای هر بلاک Scope جداگانه ایجاد میکنند.
به همین دلیل Hoisting نیز داخل هر Block Scope به صورت مستقل انجام میشود و هر بلاک دارای Temporal Dead Zone مخصوص به خود خواهد بود.
let age = 30;
if (true) {
console.log(age);
let age = 20;
}
خروجی
خروجی کد
CODE OUTPUTاگرچه متغیر age در Scope بیرونی مقداردهی شده است، اما داخل Block ابتدا موتور JavaScript به دنبال متغیر محلی میگردد و به دلیل قرار داشتن آن داخل TDZ خطا ایجاد میشود.
Hoisting توابع در JavaScript
رفتار Hoisting برای توابع با متغیرها تفاوت دارد. تابعی که به صورت Function Declaration تعریف شده باشد، قبل از اجرای برنامه به طور کامل داخل حافظه قرار میگیرد و در هر نقطه از Scope قابل فراخوانی است.
به همین دلیل بسیاری از پروژههای قدیمی از این قابلیت استفاده میکنند، هرچند امروزه بیشتر توسعهدهندگان ترجیح میدهند ابتدا تابع را تعریف و سپس آن را فراخوانی کنند تا خوانایی کد حفظ شود.
مثال Function Declaration
در مثال زیر تابع قبل از محل تعریف بدون هیچ مشکلی اجرا میشود.
sayHello();
function sayHello() {
console.log("Hello CafeAmoozesh");
}
خروجی
خروجی کد
CODE OUTPUTدلیل این رفتار آن است که موتور JavaScript کل بدنه تابع را در مرحله Creation Phase داخل حافظه قرار میدهد.
Function Expression و Hoisting
اگر تابع را داخل یک متغیر ذخیره کنیم، رفتار Hoisting دیگر مانند Function Declaration نخواهد بود. در این حالت رفتار تابع کاملاً وابسته به نوع متغیری است که برای نگهداری آن استفاده شده است.
مثال با var
showMessage();
var showMessage = function () {
console.log("Hello");
};
خروجی
خروجی کد
CODE OUTPUTTypeError:
showMessage is not a function
متغیر showMessage در زمان Creation مقدار undefined دریافت میکند. بنابراین هنگام فراخوانی هنوز تابعی داخل آن قرار نگرفته است.
مثال با let
showMessage();
let showMessage = function () {
console.log("Hello");
};
خروجی
خروجی کد
CODE OUTPUTدر این حالت متغیر داخل Temporal Dead Zone قرار دارد و حتی امکان دسترسی به آن نیز وجود ندارد.
Hoisting در Arrow Function، Async Function و Generator Function
در JavaScript تنها Function Declaration و Function Expression وجود ندارند؛ انواع دیگری مانند Arrow Function، Async Function و Generator Function نیز وجود دارند که هنگام Hoisting رفتارهای متفاوتی از خود نشان میدهند. شناخت این تفاوتها به شما کمک میکند هنگام طراحی معماری پروژه یا Debug کردن برنامه، رفتار موتور JavaScript را دقیقتر پیشبینی کنید.
نکته مهم این است که نوع تابع معمولاً تعیینکننده Hoisting نیست، بلکه نوع Declaration اهمیت دارد. اگر تابع داخل یک متغیر ذخیره شود، رفتار آن به var، let یا const وابسته خواهد بود.
| نوع تابع | Hoisting | قبل از تعریف قابل اجرا | دلیل | |
|---|---|---|---|---|
| Function Declaration | ✔ | ✔ | کل تابع در Creation Phase ثبت میشود. | |
| Function Expression | وابسته به متغیر | ✖ | تابع داخل یک متغیر ذخیره میشود. | |
| Arrow Function | وابسته به متغیر | ✖ | رفتار آن به نوع متغیر (var، let یا const) بستگی دارد. | |
| Async Function Declaration | ✔ | ✔ | مانند Function Declaration در Creation Phase ثبت میشود. | |
| Async Arrow Function | وابسته به متغیر | ✖ | داخل یک متغیر ذخیره میشود و در صورت استفاده از let یا const تا قبل از مقداردهی داخل TDZ قرار دارد. | |
| Generator Function | ✔ | ✔ | مانند Function Declaration در مرحله Creation Phase به طور کامل ثبت میشود. |
مثال اول؛ Arrow Function
از آنجا که Arrow Function معمولاً داخل یک متغیر ذخیره میشود، رفتار Hoisting آن کاملاً به نوع متغیر وابسته است. در مثال زیر متغیر با const تعریف شده و قبل از مقداردهی داخل Temporal Dead Zone قرار دارد.
printUser();
const printUser = () => {
console.log("Sara");
};
خروجی
خروجی کد
CODE OUTPUTمثال دوم؛ Async Function Declaration
اگر Async Function به صورت Declaration نوشته شود، مانند Function Declaration قبل از تعریف نیز قابل فراخوانی خواهد بود.
loadUsers();
async function loadUsers() {
console.log("Loading...");
}
خروجی
خروجی کد
CODE OUTPUTمثال سوم؛ Async Arrow Function
اگر Async Function به صورت Arrow Function تعریف شود، رفتار Hoisting آن دیگر مانند Function Declaration نیست، زیرا داخل یک متغیر ذخیره میشود.
fetchUsers();
const fetchUsers = async () => {
console.log("Users loaded");
};
خروجی
خروجی کد
CODE OUTPUTعلت این خطا این است که متغیر fetchUsers با const تعریف شده و قبل از مقداردهی داخل Temporal Dead Zone قرار دارد.
مثال چهارم : Generator Function
Generator Function نیز مانند Function Declaration در مرحله Creation Phase به طور کامل داخل حافظه قرار میگیرد و قبل از تعریف قابل استفاده است.
const generator = createNumbers();
console.log(generator.next().value);
function* createNumbers() {
yield 1;
yield 2;
}
خروجی
خروجی کد
CODE OUTPUTنکته
NOTEBest Practice
BEST PRACTICEمقایسه انواع Hoisting
| نوع | Hoist میشود؟ | قابل استفاده قبل از تعریف |
|---|---|---|
| var | ✔ | undefined |
| let | ✔ | ReferenceError |
| const | ✔ | ReferenceError |
| Function Declaration | ✔ | کاملاً قابل اجرا |
| Function Expression | وابسته به نوع متغیر | خطا |
| Arrow Function | وابسته به نوع متغیر | خطا |
مثال واقعی در پروژه
فرض کنید در یک پنل مدیریت، قبل از دریافت اطلاعات کاربر، تابع اعتبارسنجی فراخوانی میشود. اگر این تابع به صورت Function Declaration نوشته شده باشد، برنامه بدون خطا اجرا خواهد شد.
validateUser();
function validateUser() {
console.log("User validated");
}
اما اگر همین تابع به صورت Arrow Function تعریف شود، فراخوانی قبل از تعریف باعث ایجاد خطا خواهد شد و کل فرآیند ورود کاربر متوقف میشود.
نکته
NOTE
موتور JavaScript هنگام Hoisting چه کاری انجام میدهد؟
برای درک بهتر Hoisting بهتر است به جای حفظ کردن رفتارها، مراحل اجرای موتور JavaScript را بررسی کنیم. هر فایل یا تابع قبل از اجرا یک Execution Context جدید ایجاد میکند و در همین مرحله فرآیند Hoisting اتفاق میافتد.
در Creation Phase موتور JavaScript ابتدا تمام Function Declarationها را به صورت کامل داخل حافظه قرار میدهد. سپس متغیرهای var را با مقدار undefined ثبت میکند و در نهایت متغیرهای let و const را ایجاد میکند اما آنها را داخل Temporal Dead Zone نگه میدارد.
| مرحله | اتفاق |
|---|---|
| ۱ | ایجاد Lexical Environment |
| ۲ | ثبت تمام Function Declarationها |
| ۳ | ثبت متغیرهای var با مقدار undefined |
| ۴ | ثبت let و const داخل TDZ |
| ۵ | شروع Execution Phase |
Best Practice
BEST PRACTICEMemory Timeline در Hoisting
اگر بخواهیم Hoisting را به صورت تصویری بررسی کنیم، ابتدا فایل JavaScript توسط Parser خوانده میشود. سپس موتور وارد Creation Phase شده و فضای حافظه موردنیاز را ایجاد میکند. در ادامه Execution Phase آغاز شده و مقداردهی متغیرها انجام میشود.
| مرحله | وضعیت متغیر |
|---|---|
| Parsing | خواندن کد |
| Creation Phase | ثبت Declarationها |
| TDZ | عدم دسترسی به let و const |
| Initialization | اختصاص مقدار اولیه |
| Execution | اجرای دستورات |
شبیهسازی Hoisting مرحله به مرحله
فرض کنید کد زیر در حال اجرا است. ابتدا خود کد را مشاهده میکنیم و سپس دقیقاً بررسی میکنیم موتور JavaScript در هر مرحله چه تصمیمی میگیرد.
console.log(user);
var user = "Sara";
printUser();
function printUser() {
console.log(user);
}
در نگاه اول ممکن است تصور کنید برنامه از خط اول خطا میدهد، اما نتیجه اجرای واقعی متفاوت است.
| Step | Call Stack | Memory | Output |
|---|---|---|---|
| Creation | Global Context | user → undefined printUser → Function |
– |
| Execution 1 | console.log() | user → undefined | undefined |
| Execution 2 | Assignment | user → “Sara” | – |
| Execution 3 | printUser() | user → “Sara” | Sara |
Debug کردن Hoisting در Chrome DevTools
یکی از بهترین روشهای یادگیری Hoisting، مشاهده نحوه اجرای کد در Chrome DevTools است. با قرار دادن Breakpoint قبل از مقداردهی متغیرها میتوانید وضعیت Scope و مقدار متغیرها را در هر مرحله بررسی کنید.
این روش به شما کمک میکند تفاوت بین Creation Phase و Execution Phase را به صورت عملی مشاهده کنید و رفتار متغیرهای var، let و const را بهتر درک کنید.
مرحله اول: قرار دادن Breakpoint
ابتدا فایل JavaScript را در مرورگر اجرا کرده و داخل تب Sources روی اولین خط برنامه Breakpoint قرار دهید.
console.log(user);
let user = "Sara";
console.log(user);
پس از توقف برنامه، وارد بخش Scope شوید و وضعیت متغیرها را بررسی کنید.
مرحله دوم: بررسی Scope
در اولین توقف برنامه مشاهده میکنید که متغیر user در Lexical Environment ثبت شده است، اما هنوز مقدار اولیه دریافت نکرده و داخل Temporal Dead Zone قرار دارد.
مرحله سوم: اجرای خط به خط
اکنون با استفاده از دکمه Step Over اجرای برنامه را ادامه دهید. زمانی که دستور let اجرا شود، متغیر مقداردهی شده و از Temporal Dead Zone خارج خواهد شد.
Best Practice
BEST PRACTICEاشتباهات رایج درباره JavaScript Hoisting
- تصور اینکه Hoisting یعنی جابهجا شدن خطوط کد.
- فکر کردن به اینکه let و const اصلاً Hoist نمیشوند.
- یکسان دانستن Function Declaration و Function Expression.
- استفاده از var در پروژههای جدید.
- فراخوانی Arrow Function قبل از تعریف.
- نادیده گرفتن Temporal Dead Zone هنگام Debug کردن برنامه.
هشدار
WARNINGBest Practices هنگام استفاده از Hoisting
- همیشه قبل از استفاده، متغیرها را تعریف کنید.
- تا حد امکان از let و const استفاده کنید.
- از var فقط هنگام نگهداری پروژههای قدیمی استفاده کنید.
- توابع را قبل از محل فراخوانی قرار دهید.
- به جای تکیه بر Hoisting، ترتیب منطقی کد را حفظ کنید.
- برای Scopeهای کوچک از Block Scope استفاده کنید.
- هنگام Debug ابتدا Creation Phase را در ذهن شبیهسازی کنید.
Performance و سازگاری Hoisting در مرورگرها
Hoisting یکی از رفتارهای استاندارد زبان JavaScript است و توسط تمام موتورهای مدرن مانند V8، SpiderMonkey و JavaScriptCore پیادهسازی میشود. بنابراین رفتار آن در مرورگرهای جدید و Node.js تقریباً یکسان است.
از نظر Performance نیز Hoisting هزینه قابل توجهی ایجاد نمیکند، زیرا Creation Phase بخشی از فرآیند طبیعی ساخت Execution Context است و در تمام برنامهها انجام میشود.
| محیط اجرا | پشتیبانی از Hoisting | وضعیت |
|---|---|---|
| Google Chrome (V8) | ✔ | کاملاً پشتیبانی میشود |
| Microsoft Edge | ✔ | کاملاً پشتیبانی میشود |
| Mozilla Firefox | ✔ | کاملاً پشتیبانی میشود |
| Safari | ✔ | کاملاً پشتیبانی میشود |
| Node.js | ✔ | کاملاً پشتیبانی میشود |
نکته
NOTEارتباط Hoisting با سایر مفاهیم JavaScript
Hoisting تنها یکی از بخشهای فرآیند اجرای برنامه است و به تنهایی عمل نمیکند. این مفهوم ارتباط مستقیمی با Scope، Execution Context و Lexical Environment دارد و درک صحیح آن باعث میشود رفتار Closureها نیز بهتر قابل تحلیل باشد.
از طرف دیگر زمانی که عملیاتهای غیرهمزمان مانند Promise، Async/Await یا Fetch API اجرا میشوند، ابتدا مرحله Hoisting انجام شده و سپس Event Loop وظیفه مدیریت عملیات Async را بر عهده میگیرد. به همین دلیل این مفاهیم مکمل یکدیگر هستند.
منابع بیشتر
READ MORE
تمرین
EXERCISE- کدی بنویسید که تفاوت خروجی var و let را قبل از تعریف نمایش دهد.
- یک Function Declaration را به Function Expression تبدیل کرده و نتیجه را بررسی کنید.
- با استفاده از const یک مثال برای Temporal Dead Zone ایجاد کنید.
- کدی بنویسید که در آن Hoisting باعث ایجاد Bug شود و سپس آن را اصلاح کنید.
- Execution Context مثالهای بالا را مرحله به مرحله تحلیل کنید.
چالش کافه آموزش
قبل از مشاهده پاسخها، سعی کنید به سؤالات زیر پاسخ دهید.
سؤال ۱
کدام عبارت درباره Hoisting مربوط به let صحیح است؟
- اصلاً Hoist نمیشود.
- Hoist میشود اما تا قبل از مقداردهی در Temporal Dead Zone قرار دارد.
- همیشه مقدار
undefinedدارد. - مانند
varقبل از تعریف قابل استفاده است.
پاسخ
گزینه ۲ صحیح است.
سؤال ۲
چرا متغیرهای var قبل از تعریف مقدار undefined برمیگردانند؟
- چون JavaScript مقدار را حدس میزند.
- زیرا در Creation Phase با مقدار اولیه
undefinedدر حافظه ثبت میشوند. - چون در Global Scope قرار دارند.
- به دلیل وجود Event Loop.
پاسخ
گزینه ۲ صحیح است.
سؤال ۳
کدام نوع تابع قبل از تعریف نیز قابل فراخوانی است؟
- Function Expression
- Arrow Function
- Function Declaration
- Anonymous Function
پاسخ
گزینه ۳ صحیح است.
سؤال ۴
هدف از Temporal Dead Zone (TDZ) چیست؟
- افزایش سرعت اجرای برنامه
- جلوگیری از استفاده متغیر قبل از مقداردهی اولیه
- مدیریت حافظه JavaScript
- اجرای خودکار توابع
پاسخ
گزینه ۲ صحیح است.
سؤال ۵
کدام عبارت درباره Hoisting صحیح است؟
- خطوط برنامه را جابهجا میکند.
- کد را دوباره کامپایل میکند.
- فقط نتیجه فرآیند Creation Phase است و خطوط برنامه جابهجا نمیشوند.
- فقط برای توابع اتفاق میافتد.
پاسخ
گزینه ۳ صحیح است.
سؤالات متداول مصاحبه JavaScript Hoisting
۱. Hoisting در JavaScript دقیقاً چیست؟
Hoisting فرآیندی است که هنگام ایجاد Execution Context انجام میشود و طی آن Declaration متغیرها و توابع قبل از اجرای برنامه در حافظه ثبت میشوند.
۲. آیا let و const Hoist میشوند؟
بله. هر دو Hoist میشوند اما تا زمان اجرای دستور تعریف، داخل Temporal Dead Zone قرار دارند و قابل دسترسی نیستند.
۳. چرا Function Declaration قبل از تعریف قابل اجرا است؟
زیرا موتور JavaScript کل بدنه تابع را در مرحله Creation Phase داخل حافظه قرار میدهد و تابع از ابتدای Scope قابل فراخوانی خواهد بود.
۴. تفاوت Hoisting در var و let چیست؟
متغیرهای var مقدار اولیه undefined دریافت میکنند، اما let و const تا زمان مقداردهی داخل TDZ باقی میمانند و دسترسی به آنها باعث ReferenceError میشود.
۵. آیا Arrow Function نیز مانند Function Declaration Hoist میشود؟
خیر. Arrow Function معمولاً داخل یک متغیر ذخیره میشود و رفتار Hoisting آن کاملاً وابسته به نوع متغیر است.
۶. Hoisting چه ارتباطی با Execution Context دارد؟
Hoisting بخشی از Creation Phase در Execution Context است و قبل از شروع اجرای واقعی برنامه انجام میشود.
۷. آیا Hoisting باعث جابهجا شدن خطوط کد میشود؟
خیر. این تنها یک برداشت ذهنی برای توضیح رفتار موتور JavaScript است و هیچ خطی از کد جابهجا نمیشود.
سؤالات متداول کاربران (FAQ)
Hoisting در JavaScript چیست؟
Hoisting فرآیندی است که طی آن موتور JavaScript قبل از اجرای برنامه، متغیرها و توابع را در مرحله Creation Phase ثبت میکند.
آیا Hoisting یک ویژگی رسمی JavaScript است؟
خیر. واژه Hoisting در مشخصات ECMAScript وجود ندارد و صرفاً اصطلاحی است که توسعهدهندگان برای توضیح رفتار موتور JavaScript استفاده میکنند.
چرا var قبل از تعریف مقدار undefined برمیگرداند؟
زیرا هنگام ساخت Execution Context، متغیرهای var با مقدار اولیه undefined داخل حافظه قرار میگیرند.
چرا let و const خطا تولید میکنند؟
این متغیرها تا زمان اجرای دستور تعریف داخل Temporal Dead Zone قرار دارند و هرگونه دسترسی به آنها باعث ReferenceError میشود.
کدام نوع تابع بهتر است؟
در پروژههای مدرن معمولاً Function Declaration برای توابع عمومی و Arrow Function برای Callbackها و توابع کوتاه استفاده میشود.
آیا Hoisting روی عملکرد برنامه تأثیر دارد؟
خیر. Hoisting بخشی طبیعی از فرآیند اجرای JavaScript است و معمولاً تأثیر محسوسی بر Performance ندارد.
جمعبندی
در این مقاله یاد گرفتیم که Hoisting به معنی جابهجا شدن خطوط کد نیست، بلکه نتیجه فرآیند Creation Phase در Execution Context محسوب میشود. همین فرآیند باعث میشود Function Declaration قبل از تعریف قابل اجرا باشد و متغیرهای var مقدار undefined دریافت کنند.
همچنین مشاهده کردیم که let و const نیز Hoist میشوند، اما تا زمان مقداردهی داخل Temporal Dead Zone باقی میمانند. درک این تفاوت یکی از مهمترین مهارتهای هر توسعهدهنده JavaScript است و در Debug کردن برنامهها نقش بسیار مهمی دارد.
اگر مفاهیم Hoisting، Scope، Execution Context و Closures را به خوبی یاد بگیرید، درک موضوعات پیشرفتهتر مانند Event Loop، Promise، Async/Await و Fetch API نیز بسیار سادهتر خواهد شد و تحلیل رفتار موتور JavaScript برای شما کاملاً قابل پیشبینی میشود.





اولین دیدگاه رو شما برای ما ارسال و کنید
کاربر گرامی : برای ارسال دیدگاه خود ابتدا باید در سایت لاگین نمایید.