Ahmadreza Mozaffary
Ahmadreza Mozaffary
خواندن ۶ دقیقه·۳ سال پیش

یکبار برای همیشه ! هویستینگ در جاواسکریپت یعنی چه ؟ (Hoisting in Javascript)

سلام به همه برنامه نویس های عزیز و بزرگترای خودم علی الخصوص برنامه نویس های فرانت-اند و علاقمندان به زبان جاواسکریپت ?

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

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

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

خب بدون تلف کردن وقت بریم سر اصل مطلب ...

قبل از اون باید یه مفهوم دیگه رو به عنوان پیشنیاز مفهوم Hoisting بدونیم ...

که خوشبختانه قبلا خودم براش یک مقاله کوتاه و مختصر نوشتم که کمتر از ۱ دقیقه احتمالا مطالعه اش وقتتون رو بگیره اون مفهوم پیش‌نیاز چیزی نیست جز TDZ که میتونید از " اینجا " اون رو بخونید !

لطفا حتما اون رو مطالعه کنید تا هیچ سردرگمی رو توی مطالعه ادامه این مقاله تجربه نکنید اگه هم که از قبل با این مفهوم آشنایید که دمتون گرم و ادامه این مقاله رو با من باشید ?



نکته مهم⚠️ : اگه که عجله دارید و نمیخاید کل مقاله رو بخونید ، نتایج شماره ۱ ،‌۲ و سه و نتیجه کلی رو بخونید ?


خب حالا که مفهوم TDZ رو فهمیدیم میتونیم بریم سر وقت مفهوم Hoisting ، میریم که داشته باشیم ?

در مرحله اول ممکنه هر برنامه نویسی اسم این مفهوم رو بشنوه فکر کنه که جاواسکریپت میاد و تمام متغیر ها و توابع رو میاره اول بلاک کد ، اما این ۱۰۰٪ درست نیست !


خب احمدرضا تعریف درستش چیه? ؟

ببینید رفقا ، به صورت کلی هویستینگ روی متغیر ها میاد و سعی میکنه که اونا رو بیاره اول کد تا بتونیم از اونا توی خط های قبل از تعریف متغیر ( توی ناحیه TDZ اون متغیر ) ازش استفاده کنیم ، اما چطوری ? ؟

به صورت کلی ما سه نوع تعریف متغییر داریم :

  • تعریف متغیر با کلمه کلیدی var
  • تعریف متغیر با کلمه کلیدی const
  • تعریف متغیر با کلمه کلیدی let

هویستینگ میاد و تلاش میکنه که کلمه های کلیدی let و const رو (که ES6 اونا رو برای ما به ارمغان آورد) به اول بلاک کد ما Hoist کنه ! اما این کار صورت نمیگیره ، برای اثباتش میتونیم کد زیر رو داشته باشیم :

console.log(variable); const/let variable = &quotvalue&quot

همونطور که توی بلاک کد بالا میبینید ، ما اومدیم و متغیر با اسم variable رو قبل از مقدار دادن و تعریف کردنش ، فراخوانی کردیم ، به نظر شما حاصل console.log(variable) چیه ؟

به لطف Hoisting ما خروجی زیر رو داریم :

Uncaught ReferenceError: variable is not defined

پس به عنوان نتیجه ۱ ، میتونیم بگیم که :

? جاواسکریپت متغیر هایی که با let و یا const تعریف شده باشند رو Hoist نمیکنه ، یعنی ما ارور خواهیم داشت !


اما الان سوالی که پیش میاد احتمالا این هست که ، خب رفتار جاواسکریپت با var چطوریه ؟

خب ما اگه کد مشابه قبل رو داشته باشیم با این تفاوت که متغیر با var تعریف شده باشه یعنی :

console.log(variable); var variable = &quotvalue&quot

جاواسکریپت میاد و این متغیر رو که اینجا اسمش variable هست و با کلمه کلیدی var تعریف شده رو تلاش میکنه به اول بلاک کد Hoist کنه ، و البته که این کار رو میکنه ? !

خب الان که گفتیم این متغییر Hoist میشه به ابتدای بلاک ، احتملا توی ذهنتون فکر کردین که مقدار خروجی حاصل از console.log(variable) رشته "value" باشه ، اما اینطور نیست !

متغیری که با کلمه کلیدی var تعریف شده باشه ، فارغ از این که مقدار نسبت داده شده بهش چی باشه ، وقتی روی اون Hoisting اعمال میشه ( یعنی اون متغیر Hoist میشه ) مقدار "undefined" رو به ما بر میگردونه ? !

میدونم که از نظرتون عجیبه این رفتار ، ولی خب همینه که هست ? و ما کاری نمیتونیم بکنیم ، و یکی از علت های مهمی که بعد ES6 دیگه استفاده از var توصیه نمیشه هم همین رفتار هست ?

پس به عنوان نتیجه ۲ ، داریم که :

? متغیری که با کلمه کلیدی var تعریف شده باشه ، فارغ از مقدار assign شده به اون در ناحیه TDZ مختص به خودش بعد از Hoist شدن ، مقدار "undefined" رو به ما بر میگردونه !


تا به اینجا ، هویستینگ رو روی متغیر ها بررسی کردیم ...

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

ما برای تعریف توابع هم در جاواسکریپت سه روش کلی و نهایی داریم:

  • تعریف تابع به صورت Function Declaration
  • تعریف تابع به صورت Arrow Function
  • تعریف تابع به صورت Function Expression

خب بگذارید اول تکلیف دوتای اخر رو براتون مشخص کنم مثال زیر تعریف تابع برای دو حالت اخر هست :

// Arrow Function const sumArrow = (x, y) => x + y; // Function Expression const sumExpression = function (x, y) { return x + y; };

اگه که به شیوه تعریف این توابع دقت کنید ، میبینید که ما بالاخره این توابع رو توی یک متغیر تعریف کردیم که از کلمه کلیدی const برای این کار استفاده شده ( بدیهیه که میتونیم از let استفاده کنیم اما منطقی نیست چرا که قرار نیست بعدا چیزی رو به اون ها assign کنیم ) و همونطور که حدس زدید و بالا توضیح دادیم جاواسکریپت عینا و دقیقا مثل متغیر ها با این نوع توابع رفتار میکنه ، یعنی Hoisting عملا صورت نمیگیره !!!


اما برای حالت اول لیست بالا ، که تعریف تابع به روش Function Declaration هست

// Function Declaration function sumDeclaration(x, y) { return x + y; }

جاواسکریپت و میاد و کامل Hoisting رو روی این نوع توابع پیاده سازی میکنه و به صورت صحیح و کاملا درست این توابع به اول بلاک کد مختص خودشون Hoist میشن ?

در نتیجه ، به عنوان نتیجه ۳ داریم که :

? اگه که تابع به صورت Function Declaration تعریف شده باشه به صورت کاملا درست روی اون Hoisting انجام میشه و اون تابع صحیح به اول بلاک کدش Hoist میشه ولی اگه که تابع به صورت Arrow Function یا Function Expression تعریف شده باشه ، چون اونا رو عملا توی یه متغیر ذخیره کردیم ( const / let ) جاواسکریپت میاد و با اونا مثل یک متغیر رفتار میکنه پس توابعی که به یکی از این دو صورت تعریف شده باشن روی اونها Hoisting صورت نمیگیره و داخل TDZ خودشون اگر که اون ها رو call کنیم ، ارور خواهیم داشت !



خب اگه که بخوایم که باهم طبق نتایج ۱ ، ۲ و ۳ بالا به یک نتیجه کلی برسیم ، میتونیم بگیم که :

? هویستینگ فقط روی توابعی که به صورت Function Declaration تعریف شده باشند صحیح کار میکنه یعنی میتونیم اون هارو داخل TDZ خودشون فرا بخونیم ! ( اصلا این کار توصیه نمیشه که تابع رو تعریف کنیم و در خطوط قبلش استفاده کنیم ، هرچند شدنی هست ولی clean نیست و مارو در آینده سردرگم میکنه ) .

? هویستینگ روی متغیر هایی که با کلمه کلیدی var تعریف شده باشند عمل میکنه ولی داخل TDZ مختص خودشون مقدار "undefined" رو به ما ارجاع میده !

? هویستینک روی سایر روش های تعریف تابع و متغیر عمل نمیکنه و داخل TDZ اونا به ما ارور میده !



خب به آخر این مقاله رسیدیم ،‌خیلی خیلی ممنونم که وقت با ارزشتون رو گذاشتین و این مقاله منو خوندین

موضوع پیشنهادی ، انتقادی از مقاله بود با کمال میل توی کامنت ها یا ایمیل منتظرتون هستم

اگه که راضی بودین یا براتون مفید بود اول ممنون میشم که لایک کنید و برای دوستانتون انتقال بدین ??

hoistingهویستینگجاواسکریپتjs
من احمدرضا مظفری به عنوان Software developer توی شرکت همکاران سیستم مشغول هستم ، توی زمینه وب ، میخونم ، یادمیگیرم ، مینویسم .
شاید از این پست‌ها خوشتان بیاید