اندر احوالات جاوااسکریپت (قسمت چهارم)

خب خب ما هنوزم توی Execution Context گیر کردیم

توی مقاله قبل به یکی از اون سه موردی که توی Execution Context بود یعنی scope مفصل پرداختیم

حالا توی این مقاله به مورد variable environment که یه جورایی Hoisting میشه میپردازیم

خود کلمه Hoisting به معنی بالابردن هستش یعنی یک متغیر به بالاترین سطح (Top-level) scope خودش بره یا اصطلاح خارجیش میگیم variables lifted to the top of their scope

یعنی اگه variable، function و class داشتی اینا به بالاترین سطح از اسکوپ خودشون میرن

کلاس ها توی جاوااسکریپت چیزی نیستن جز تابع، اگه میخوایی بگی اون کلمه class که توی ES6 معرفی شده پس چیه ؟ باید بگم اون فقط یه پوسته اس برای کدنویسی تمیز‌‌‌‌‌‌تر و پشت قضیه اش همش تابع اس و object بعدن به این موضوع مفصل میپردازیم

الان عصبانی شدی میگی آقا یعنی چی هی میگی بالاترین سطح از اسکوپ خودشون ؟؟؟

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

عصبانیت نداره که توی مثال زیر میفهمی چی میگم، فرض کن کد زیر رو ما نوشتیم

var name = 'Mohammad';
console.log(name);

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

var name = undefined;
name = 'Mohammad';
console.log(name);

عه چی شد ؟؟؟ اومد name رو برداشت به بالاترین سطح اسکوپ خودش برد و بهش مقدار undefined داد

در واقع داره میگه من name رو میبرم اون بالا ولی مقدارش نمیدونم چیه پس بهش undefined میدم تا وقتی رسیدم بهش مقداری که تو دادی رو (یعنی 'Mohammad') جاگذاری میکنم توی name (برنامه نویس: ما داریم اینجا زحمت میکشیم)

برای اثبات حرفم یه کنسول لاگ بندازی قبل اون var name = Mohammad میبینی که مقدار undifined رو بهت پس میده

این چه معنی میده ؟؟؟ به این معنیه که تو قبل اینکه متغیرت initialize بشه مقدار میگیره اونم چی ؟undefined و میتونی بهش دسترسی داشته باشه و این خیلی ممکنه وحشتناک بشه و تولید باگ کنه

یه مثال دیگه بزنیم، این‌بار با توابع

همون طور که می‌دونید سه نوع تابع توی جاوا‌اسکریپت داریم

  1. function declaration
  2. function expression
  3. arrow function

وقتی یه تابعی از نوع function declaration داریم مثل مثال زیر :

showName();
function showName () {
        console.log(name);
}

می‌تونیم قبل از تعریف کردنش صداش بزنیم و این به لطف وجود Hoisting هستش کلا علت وجود Hoisting هم دقیقا همینه

خب تا اینجا ما همش راجب var و function declaration حرف زدیم و Hoisting رو توی اونا بررسی کردیم

اما let, const و توابع نوع arrow و expression چطور ؟؟؟

اول let, const رو بررسی کنیم‌:

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

اصلا ولش کن، کد زیر رو ببین تا بهت بگم جریان چیه

// var Hoisting
console.log(name);
var name = 'Mohammad'; 
console.log(name);

// let Hoisting
console.log(name); 
let name = 'Mohammad';  
console.log(name);

همون طور که میبینید سه خط کد اول که با var هستن اجرا میشن و مقدار name اول میشه undefined(به خاطر همون hoisting) و مقدار name دوم، بعد از تعریف var میشه 'Mohammad'

اما توی سه خط کد دوم وقتی جاوااسکریپت به خط اول که میرسه میگه عه عه name رو تعریف کردی ولی مقدار دهیش نکردی؟فکر کردی من مثل var بی دروپیکر هستم ؟ پس ارور زیر رو میده :

ReferenceError: Cannot access 'name' before initialization

در واقع let, const هم Hoisted میشن ولی دیگه مقدار undefined نمیگیرن و قبل از تعریف قابل دسترس نیستن

دقت کنید خطا داره میگه name مقدار‌دهی نشده (نشون دهنده اینه که Hoisting داره کار میکنه) نه اینکه تعریف نشده بین دوتا فرق هست
not defined ==! not initialize
یه مطلب کوچیک :
اگه نمیدونید declaration و assignment و initialize فرقشون چیه کد زیر رو ببینید
let name;                  =>   declaration (define variable)
name = 'Ali';              =>   initialize
let name = 'ali' ;        =>   assignment = declaration + initialize

اما توابع arrow و expression چطور‌ ؟؟؟ خب بستگی داره با چی تعریفشون کنی

اگه با var تعریف بشن خب رفتارشون توی بحث Hoisting عین همون var میشه اگه با const, let تعریف بشن هم که دیگه Hoisting اشون طبیعتا شبیه خود let, const هستش

خب آخرین مبحثی که بهش میپردازیم Temporal Dead Zone هستش

عکس زیر رو ببین

Temporal dead zone
Temporal dead zone


به اون منطقه ای که از اسکوپ متغیر مورد نظر تا مقداردهی کردن اون متغیر هست رو منطقه TDZ میگیم

الان کد توی عکس رو ببین، اسکوپ متغیر job میشه بلاک if (علتش؟ تو مقاله قبل گفتمش) و توی خط چهارم بلاک if هم مقداردهی شده اون منطقه از شروع اسکوپش تا مقداردهیش رو که متغیر در دسترس نیست رو میگن منطقه مرگ موقتی یا TDZ
بازم تکرار میکنم ما ارور initialize گرفتیم یعنی جاوااسکریپت میدونه متغیر تعریف شده (declare) ولی مقداردهی نشده (initialize) و این با ارور دوم که not define هست فرق میکنه یعنی کلا ما متغیری با این اسم تعریف نکردیم (مثل x)



امیدوارم بدردتون خورده باشه اگه سوالی چیزی داشتین یا دیدین جایی رو اشتباه گفتم تو نظرات بگید

اگه هم دوست داشتین توی کانال تلگرامم عضو بشید LearnByLearn@

ممنون