
درود دوستان. توی این پست روشهای مختلف ساخت متغیرها رو بطور مفصل با هم بررسی میکنیم.
کلی ویژگی جالب و جدید توسط ES6 به جاوااسکریپت اضافه شده و این زبان رو محبوب تر از همیشه کرده. در کنار var که تنها روش موجود در جاوااسکریپت بود، ES6 دوتا روش جدید برای ساخت متغیرها معرفی کرده که let و const هستن. اگه تا الان از var استفاده میکردین و کاربرد let و const رو نمیدونین، شاید از خودتون بپرسین من که تا الان از var استفاده میکردم و هیچ مشکلی وجود نداشت، پس چرا باید از let استفاده کنم؟ بهتره که این مقاله رو خوب بخونین؛ چون پیشنهاد میشه کم کم با var خداحافظی کنین.
قبل از شروع بهتره با چند تا تعریف آشنا بشیم.
اسکوپ (Scope) یا حوزه، به جاهایی گفته میشه که متغیرها قابل دسترسی و استفاده هستن
یعنی یک متغیر توی چه جاهایی قابل دسترسی هست. مثلا توی تابع یا کلاس.
متغیرهای سراسری دارای حوزه Global هستن (Global Scope). یعنی همه جا در دسترس هستن.
این واژه توی زبان پارسی یعنی بالا بردن یه چیزی.
هویستینگ Hoisting توی جاوااسکریپت مکانیزمی هست که باعث میشه قبل از اجرای برنامه، متغیرها و توابع، به بالاترین سطح حوزه خودشون جابجا بشن.
با Hoisting توی هر آیتم var و let و const بیشتر آشنا میشیم. حالا هر ۳ مورد رو میتونیم بهتر بررسی کنیم.
قبل از اینکه ES6 معرفی بشه، تنها راه موجود ساخت متغیرها تو جاوااسکریپت var بود. استفاده از var باعث به وجود اومدن مشکلاتی میشد و به همین دلیل به وجود اومدن یک راه جدید رو الزامی کرد. قبل از اینکه درباره این مشکلات صحبت کنیم، بیاین درباره var بیشتر بدونیم.
متغیرهایی که با var تعریف میشن، میتونن یا حوزه سراسری داشته باشن یا لوکال (محلی). یک متغیر وقت بیرون از یک تابع تعریف شده باشه حوزه سراسری داره. یعنی وقتی یک متغیر با var بیرون از یک تابع تعریف شده باشه، توی همه جای برنامه در دسترس هست. حتی درون تابع:
var x = "This is a book" function cookie() { alert(x); } cookie(x); // This is a book
توی مثال بالا، ما متغیر x رو درون تابع هم داریم.
وقتی یک متغیر با var درون یک تابع تعریف میشه، حوزه این متغیر لوکال هست. یعنی فقط داخل همون تابع بهش دسترسی داریم:
function yoo() { var x = 1; } yoo(); alert(x); // error: x is not defined
وقتی متغیری مثلاً x، با var تعریف میشه، این قابلیت وجود داره که یک متغیر دیگه با var، با همون نام، یعنی x، تعریف بشه:
var color = "Yellow" var color = "Navy" // ok
به کد زیر و به اینکه متغیر y کجا تعریف شده دقت کنید:
alert(y); // undefined var y = "Street"
در واقع کد بالا توی جاوااسکریپت بصورت زیر تفسیر میشه:
var y; alert(y); // undefined y = "Street"
همونطور که میبینیم، برای y یک Hoisting صورت گرفت. یعنی خط ۲ توی کد اول، باعث شد که y بره به اول حوزه خودش و با مقدار undefined تعریف بشه.
به مثال زیر دقت کنین:
var greeter = "Hey Hi" var times = 4; if (times > 3) { var greeter = "Hello" } alert(greeter) //"Hello"
وقتی توی خط سوم شرط ما برقرار میشه، متغیر greeter دوباره تعریف و مقدارش عوض میشه. خب اگه بطور عمد این کار رو انجام داده باشیم، ظاهرا مشکلی نداره. اما وقتی متغیر greeter از قبل توی کد ما تعریف شده باشه ولی ما از وجودش بی خبر باشیم، احتمال اینکه کد ما دچار باگ بشه زیاده. اونم باگی که ظاهراً مخفیانه هست! :)
برای همین دلایل بود کهletوconstمعرفی شدن.
متغیرهایی که با let تعریف میشن، دارای اسکوپ بلاکی (Block Scoped) هستن. یعنی چی؟ بلاک به قسمتی از کد گفته میشه که بین براکت { } قرار میگیره. پس متغیرهایی که با let توی بلاک تعریف میشن، فقط توی همون بلاک قابل دسترسی هستن، که به اصطلاح میگن Block Scoped. مثال زیر رو ببینید:
let greeting = "Say Hi" let times = 4; if (times > 3) { let hello = "Say Hello" alert(hello); // "Say Hello" } alert(hello) // error: hello is not defined
متغیری که توی بلاک if تعریف شد، فقط توی همون بلاک قابل دسترسی بود و ما توی خط آخر کد بهش دسترسی نداشتیم.
متغیرهای let میتونن مقدار جدیدی بگیرن، ولی نمیتونن دوباره تعریف بشن:
let x = 24; x = 28; // ok
کد بالا کاملاً درسته و بدون مشکل. اما کد زیر به ما ارور میده، چون داریم یک متغیری رو که قبلا با let (یا var) تعریف شده رو دوباره با let تعریف میکنیم:
let x = 24; let x = 28; // error: redeclaration of let x // ... var y = 45; let y = 48; // error: redeclaration of let y
پس با توجه به اینکه متغیرهای let بلاک اسکوپ هستن، میشه داخل اسکوپهای مختلف متغیرهایی با همون نام رو با let تعریف کرد. بنابراین کد زیر بدون مشکل اجرا میشه:
let greeting = "Hi" if (true) { let greeting = "Hello" alert(greeting); //"Hello" } alert(greeting); //"Hi"
با توجه به کد بالا، مشکلاتی رو که تو قسمت var بررسی کردیم، دیگه برای let به وجود نمیاد.
همونطوری که برای var داشتیم، متغیرهای let هم موقع تفسیر، به بالای حوزه خودشون میرن. توی عمل Hoisting، برخلاف var که با مقدار undefined پیادهسازی میشن، متغیرهای let با هیچ مقداری پیادهسازی نمیشن. بنابراین وقتی متغیری رو میخوایم قبل از پیادهسازی استفاده کنیم، خطا میگیریم. درصورتی که توی var هیچ خطایی نمیگرفتیم و فقط مقدار undefined رو به ما تحویل میداد:
alert(f); let f = 12; // ReferenceError: can't access lexical declaration `f' before initialization
متغیرهایی که با const (کانست) تعریف میشن، همون ویژگیهایی رو دارن که متغیرهای let دارن، با این تفاوت که مقدار متغیرهای const رو دیگه نمیشه تغییر داد.
متغیرهای const مثل let بلاک اسکوپ هستن؛ یعنی همونطور که توی قسمت let توضیح دادم، متغیرهای const هم فقط توی حوزه خودشون قابل دسترسی هستن.
متغیرهای const وقتی تعریف و مقداردهی بشن، دیگه نمیتونن دوباره تعریف و همچنین مقداردهی بشن.
const p = 10; p = 4; // TypeError: invalid assignment to const `p'
const p = 12; const p = 24; // SyntaxError: redeclaration of const p
این قضیه درباره متغیرهایی که مقدار آبجکتی دارن فرق میکنه. وقتی یک متغیر const یک مقدار آبجکتی داره، آیتمهای موجود در آبجکت رو میشه بدون هیچ مشکلی تغییر داد:
const person = { name: "John", lastname: "Doe" } person.name = "Davood" console.log(person); // { name: "Davood", lastname: "Doe" }
این نکته رو در نظر داشته باشید که ما نمیتونیم کل آبجکت رو جایگزین کنیم. کد زیر به ما خطا برمیگردونه:
const person = { name: "John", lastname: "Doe" } const person = { name: "David", lastname: "Beckham" } // SyntaxError: redeclaration of const person
متغیرهای const همیشه باید با یک مقدار پیادهسازی بشن:
const u; // SyntaxError: missing = in const declaration
هویستینگ Hoisting در const درست مثل let هست. یعنی متغیرها به بالای حوزه خودشون میرن ولی پیادهسازی نمیشن. پس اگه متغیری رو قبل از اینکه پیادهسازی کنیم صدا بزنیم، خطا میگیریم.
خب دوستان امیدوارم از این مقاله استفاده کرده باشین. اگه سوال یا نظری دارید حتما توی قسمت نظرات از من بپرسید.
منبع: