مقدمه
در گذشته تنها راه تعریف متغیرها در جاوااسکریپت استفاده از var بود، اما با معرفی ES6،
کلیدواژه let (و const) به زبان اضافه شد. تفاوت میان var و let بیشتر از چیزی است که
تصور میشود و دانستن جزئیات آن باعث میشود خطاهای مخفی و پیچیده کمتری در پروژهها رخ دهد.
درک تفاوتها به شما کمک میکند متغیرهای امنتر و پیشبینیپذیرتری بسازید، از مشکلات scope و
hoisting جلوگیری کنید و کدهای مدرنتر و خواناتری بنویسید.
محدوده متغیرها
مهمترین تفاوت var و let در محدوده (scope) متغیرهاست؛ یعنی محدودهای که
متغیر در آن معتبر محسوب میشود و قابل دسترسی است.
-
var از نوع function scoped است؛ این یعنی اینکه متغیرهای تعریف شده با var اگر
درون یک تابع
تعریف شوند،
از بیرون تابع در دسترس نیستند اما اگر در هر بلاک دیگری (مثل یک بلاک شرطی if) تعریف شوند، از
بیرون بلاک
هم در دسترس هستند. این موضوع خیلی منطقی نیست و با انتظاری که برنامهنویسان دارند، همخوانی
ندارد.
-
let از نوع block scoped است؛ یعنی متغیرهای تعریفشده با let فقط در همان بلاکی
که تعریف شدهاند،
در دسترساند و از خارج از بلاک نمیتوانیم به آنها دسترسی داشته باشیم. از این نظر، let
تفاونی بین یک بلاک تابع با یک بلاک شرطی یا هر بلاک دیگر قائل نیست و اجازه دسترسی از خارج
از بلاک را نمیدهد.
به مثال زیر نگاه کنید.
JAVASCRIPT
{
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
متغیر a که با var تعریف شده از خارج از بلاک، قابل دسترسی است اما b فقط داخل
بلاک معتبر
است و بیرون آن خطا میدهد.
در مثال زیر، دو متغیر درون یک بلاک if تعریف شده است. متغیری که با var تعریف شده،
از بیرون از
بلاک هم در دسترس است اما متغیر تعریفشده با let خیر.
JAVASCRIPT
if (true) {
var x = 10;
let y = 20;
}
console.log(x);
console.log(y);
در برخی منابع آموزشی این موضوع اینطور تفسیر شده که در جاوااسکریپت، بلاک if نشتی دارد و
متغیرها در بیرون از آن
در دسترساند اما بدانید که این حرف تا زمانی معتبر بود که خبری از let نبود. در واقع، مسئله
نشتی داشتن
بلاک if نیست بلکه function scoped بودن var است که باعث میشود متغیرهایی که با
استفاده از var در هر
بلاکی (غیر از تابع) تعریف میشوند، از خارج از بلاک هم در دسترس باشند.
ویژگی Hoisting
یک تفاوت مهم دیگر بین var و let این است که var به یک ویژگی با نام Hoisting
پایبند است اما let نه.
Hoisting لغتاً به معنای بالا کشیدن است و در اینجا به این موضوع اشاره میکند که متغیرهای
تعریفشده با
var به بالای بلاک منتقل میشوند. به مثال زیر نگاه کنید.
JAVASCRIPT
console.log(x);
var x = 10;
console.log(y);
let y = 20;
در اینجا اعلان (declaration) متغیر x که با var تعریف شده بهخاطر پایبندی به
ویژگی hoisting به بالای کدها منتقل میشود و بنابراین، این متغیر در خط اول در دسترس است.
تاکید میکنم که فثط اعلان متغیر است که hoist میشود و برای مقداردهی متغیر چنین اتفاقی رخ
نمیدهد.
به همین دلیل است که خط اول منجر به چاپ مقدار undefined میشود نه مقدار 10.
از طرف دیگر، در مورد متغیر y که با let تعریف شده و بنابراین به hoisting پایبند
نیست،
دسترسی قبل از تعریف متغیر ممکن نیست و به خطا میانجامد.
بازتعریف (Redeclaration) متغیرها
var به شما اجازه میدهد چند بار متغیر را با یک نام در یک محدوده تعریف کنید اما let
چنین چیزی را
مجاز نمیداند و در صورت بازتعریف خطا میدهد. مثال زیر را ببینید.
JAVASCRIPT
var z = 5;
var z = 6;
let w = 7;
let w = 8;
از این نظر هم رفتار let منطقیتر و قابل انتظارتر است. در مجموع، var به خاطر
ویژگیهای عجیب و غریبی که دارد، نباید در جاوااسکریپت مدرن مورد استفاده قرار گیرد اما به
خاطر اینکه در کدهای قدیمی به var برمیخوریم و حتی بعضی کتابخانههای جاوااسکریپتی هم از
آن استفاده میکنند، باید با همین ویژگیهای عجیب هم آشنا باشیم.
همیشه توصیه میشود برای تعریف متغیرها در کد مدرن جاوااسکریپت از let (و const) استفاده کنید. این
کار باعث جلوگیری از خطاهای رایج، افزایش امنیت و خوانایی کد میشود. var فقط در کدهای بسیار قدیمی
کاربرد دارد.