تفاوت var و let و const در جاوا اسکریپت (با مثال)❤️
تفاوت var و let و const در جاوا اسکریپت چیست؟ یکی از سوالات مصاحبه برنامه نویسی برای فرانتاند دولوپر، تفاوت var و let و const در جاوا اسکریپت است. شاید در نگاه سطحی شباهت زیادی بین var و let و حتی const باشد. اما در نگاهی عمیقتر خواهیم دید که تفاوت متغیرهای var و let در جاوا اسکریپت و ثابت const در جاوا اسکریپت چیست؟ در این مقاله از آموزش برنامه نویسی، کاربرد var و let و const در جاوا اسکریپت و نحوه استفاده از آنها میپردازیم.
در این مقاله موضوعات زیر را بررسی خواهیم کرد:
- متغیر چیست؟
- ثابت چیست؟
- متغیر var در جاوا اسکریپت چیست؟
- متغیر let در جاوا اسکریپت چیست؟
- ثابت const در جاوا اسکریپت چیست؟
- تفاوت var و let و const در جاوا اسکریپت چیست؟
- مشکلات استفاده از var در جاوا اسکریپت چیست؟
- خلاصه تفاوت var و let و const در جاوا اسکریپت
- تفاوت var و let و const در جاوا اسکریپت در یک نگاه
- چه زمانی از var و let و const در جاوا اسکریپت استفاده کنیم؟
متغیر چیست؟
قبل از اینکه به تفاوت var و let و const در جاوا اسکریپت را بررسی کنیم، ابتدا باید بدانیم که متغیر چیست؟ «متغیر» به انگلیسی «Variable» در برنامه نویسی، یک مکانیزم است که برای ذخیره و نگهداری دادهها در حافظه استفاده میشود. متغیرها در برنامه نویسی به صورت نمادین نامگذاری میشوند و میتوانند مقادیر مختلف را در طول اجرای برنامه ذخیره کنند.
فرض کنید متغیری با نام age داریم که سن کاربر را در خود ذخیره میکند. برای مثال یک کاربری امسال 28 سال دارد. سال بعد سن او 29 میشود. پس age میتواند در طول کدهای برنامه تغییر کند. این تغییرات، باید در یک جا ذخیره شوند که در اصطلاح برنامه نویسی به آنها متغیر (Variable) میگوییم. همچنین فرض کنید یک متغیر با نام firstName داریم که نام کاربر را در خود ذخیره میکند. نام کاربر Reza است و میخواهیم آن را به Ali تغییر دهیم. چنین مقادیری نیر باید در متغیر ذخیره شوند.
اگر مقدار یک متغیر در جاوا اسکریپت از نوع عددی باشد (مانند سن)، نوع متغیر Number و اگر رشتهای باشد (مانند نام)، از نوع String است. البته انواع دیگری از متغیرها مانند Array و Object و... داریم که از نام بردن آنها صرف نظر میکنیم.
متغیرهای var و let در جاوا اسکریپت، به طور پویا نوع داده خود را تعیین میکنند و این بدان معناست که نیازی نیست قبل از استفاده از متغیر، نوع داده (Object ،Array ،String ،Number و...) آن را مشخص کنید.
ثابت چیست؟
همچنین قبل از بررسی تفاوت var و let و const در جاوا اسکریپت، باید بدانیم که ثابت چیست؟ «ثابت» به انگلیسی «Constant» در برنامه نویسی یک نوع ویژه از متغیر است که مقدار آن در طول اجرای برنامه تغییر نمیکند. یعنی بعد از تعریف و اختصاص مقدار اولیه به یک ثابت، نمیتوانید مقدار آن را تغییر دهید.
برای مثال عدد پی (PI) در ریاضی با دو رقم اعضار برابر است با 3.14 که این عدد همیشه ثابت است و در هیچ جای برنامه تغییر نخواهد کرد، چنین مقادیر باید در جایی ذخیره شوند که در اصطلاح برنامه نویسی به آنها ثابت (Constant) میگوییم.
در ثابت const در جاوا اسکریپت نیز مانند متغیرها، انواع دادهها (Object ،Array ،String ،Number و...) را داریم، که بهطور پویا نوع داده خود را تعیین میکنند. یعنی نیازی نیست که قبل از استفاده از ثابت، نوع داده (Object ،Array ،String ،Number و...) آن را مشخص کنید.
متغیر var در جاوا اسکریپت چیست؟
در ادامه مقاله تفاوت var و let و const در جاوا اسکریپت، باید متغیر var را بررسی کنیم. متغیر var در جاوا اسکریپت چیست؟ در جاوا اسکریپت، کلمه کلیدی «var» مخفف «Variable» برای تعریف متغیرها استفاده میشود.
به عنوان مثال، میتوانیم متغیری با نام «count» برای شمارش عدد را با استفاده از متغیر var بهصورت زیر تعریف کنیم:
var count = 1;
در کد بالا یک متغیر با نام count داریم چون به اول آن کلمه کلیدی var را اضافه کردهایم. این متغیر از عدد 1 شروع میشود و در طول برنامه افزایش (تغییر) پیدا میکند.
متغیر let در جاوا اسکریپت چیست؟
در ادامه مقاله تفاوت var و let و const در جاوا اسکریپت، باید متغیر let را بررسی کنیم. متغیر let در جاوا اسکریپت چیست؟ در جاوا اسکریپت، کلمه کلیدی «let» نیز مانند var برای تعریف متغیر استفاده میشود. متغیر let در ES6 معرفی شد و نسبت به var جدیدتر است و تفاوتهایی دارد که در ادامه به بررسی آنها میپردازیم.
اگر بخواهیم برای شمارش اعداد از متغیری که با نام «count» در مثال بالا استفاده کردیم، با استفاده از متغیر let تعریف کنیم، بهصورت زیر عمل میکنیم:
let count = 1;
پس در ظاهر قضیه، متغیر var و let در جاوا اسکریپت شبیه هم هستند و فقط کلمه کلیدی آنها متفاوت است. اما در بررسیهای بعدی تفاوتهای اصلی var و let در جاوا اسکریپت را بررسی خواهیم کرد.
ثابت const در جاوا اسکریپت چیست؟
در ادامه مقاله تفاوت var و let و const در جاوا اسکریپت، باید ثابت const را بررسی کنیم. ثابت const در جاوا اسکریپت چیست؟ در جاوا اسکریپت، کلمه کلیدی «const» برای تعریف یک ثابت استفاده میشود. ثابت const در ES6 همزمان با let معرفی شد که در ادامه آن را بررسی خواهیم کرد.
اگر بخواهیم عدد پی (PI) که یک عدد ثابت است را با استفاده از ثابت const بنویسیم، بهصورت زیر عمل میکنیم:
const PI = 3.14;
در مثال بالا یک ثابت با نام PI تعریف کردهایم که مقدار آن برابر است با 3.14 و این مقدار هیچوقت نمیتواند تغییر کند چون با کلمه کلیدی const تعریف شده است.
تفاوت var و let و const در جاوا اسکریپت چیست؟
اکنون که با متغیرهای var و let در جاوا اسکریپت و همچنین ثابت const در جاوا اسکریپت آشنا شدیم، باید تفاوت var و let و const در جاوا اسکریپت را بیشتر بررسی کنیم. برخی از تفاوتهای var و let و const در جاوا اسکریپت عبارتاند از:
- مقداردهی اولیه (Initializer)
- مقداردهی دوباره (Reassign)
- تعریف مجدد (Redeclaring)
- استفاده از حافظه (RAM)
- بالا بردن (Hoisting)
- محدوده (Scope)
مقداردهی اولیه (Initializer)
اولین تفاوت var و let و const در جاوا اسکریپت، در Initializer یا مقداردهی اولیه است. متغیر var و let هم میتوانند مقدار اولیه داشته باشند و هم میتوانند نداشته باشند و در طول برنامه مقداردهی شوند. اما ثابت const حتما باید مقدار اولیه داشته باشد؛ چون ثابت است و در طول برنامه نمیتوان مقدار آن را تغییر داد. به مثال زیر دقت کنید:
var one;
let two;
const three; //Uncaught SyntaxError: Missing initializer in const declaration
متغیر one با کلمه کلیدی var و متغیر two با کلمه کلیدی let در مثال بالا بدون مقدار اولیه هستند و میتوانند در طول برنامه مقدار جدیدی به آنها اضافه کرد و یا مقدار آنها را تغییر داد. اما ثابت three با کلمه کلیدی const با SyntaxError مواجه شده است چون حتما باید یک مقدار اولیه داشته باشد. برای رفع این مشکل از کد زیر استفاده میکنیم:
const three = 3;
همانطور که میبینید، مقدار اولیه ثابت three را عدد 3 قرار دادیم و مشکل SyntaxError برطرف گردید.
نتیجهگیری میکنیم که var و let در جاوا اسکریپت از لحاظ Initializer یا مقداردهی اولیه مشابه هم هستند و میتوان برای آنها مقدار اولیه تعریف نکرد. اما const در جاوا اسکریپت، حتما باید مقدار اولیه داشته باشد.
مقداردهی دوباره (Reassign)
دومین تفاوت var و let و const در جاوا اسکریپت، در Reassign یا مقداردهی دوباره است. به مثال زیر توجه کنید:
var age = 28;
age = 29;
یک متغیر var age با مقدار 28 داریم. در خط بعدی وقتی age را بدون کلمه کلیدی var بنویسیم، یعنی مقدار اولیه آن را میخواهیم تغییر دهیم. پس age برابر با 29 میشود. در حقیقت در خط اول یک متغیر age با کلمه کلیدی var تعریف کردیم و مقدار آن را برابر 28 قرار دادیم. در خط بعدی نیز مقدار این متغیر را به 29 تغییر دادیم.
اگر در خط دوم نیز به اول آن کلمه کلیدی var را اضافه میکردیم، تغییردهی مقدار نبود بلکه تعریف مجدد متغیر بود که در قسمت بعدی (Redeclaring) با آن آشنا خواهیم شد. اکنون به مثال زیر توجه کنید:
let age = 28;
age = 29;
اگر متغیر age را با کلمه کلیدی let تعریف کنیم، مانند var میتوانیم در خط بعدی مقدار اولیه آن را بدون گذاشتن کلمه کلیدی let تغییر دهیم. اما در const چطور؟ به مثال زیر دقت کنید:
const age = 28;
age = 29; //Uncaught TypeError: Assignment to constant variable.
وقتی از کلمه کلیدی const استفاده کنیم، نمیتوانیم مقدار اولیه آن را تغییر دهیم و با خطای TypeError مواجه خواهیم شد. چون همانطور که در قسمت ثابت const گفته شد، constها قابل تغییر نیستند و مقدار آنها همیشه ثابت است.
پس نتیجهگیری میکنیم که var و let در جاوا اسکریپت از لحاط Reassign یا مقداردهی دوباره شبیه هم هستند. اما const در جاوا اسکریپت، قابل مقداردهی دوباره نیست.
تعریف مجدد (Redeclaring)
سومین تفاوت var و let و const در جاوا اسکریپت، در Redeclaring یا تعریف مجدد است. متغیر var، قابلیت تعریف مجدد را دارد. به مثال زیر توجه کنید:
var color = "Red";
var color = "Blue";
همانطور که در کد بالا مشاهده میکنید، مقدار متغیری با نام color با کلمه کلیدی var برابر با Red است. سپس مقدار همان متغیر var را با نام تکراری color برابر Blue قرار دادهایم و هیچ خطایی نداریم. اما به مثال زیر دقت کنید:
let color = "Red";
let color = "Blue"; //Uncaught SyntaxError: Identifier 'color' has already been declared
در کد بالا وقتی از کلمه کلیدی let برای تعریف متغیر استفاده کنیم، مجددا با همان نام تکراری color نمیتوانیم آن را تعریف کنیم چون با خطای نحوی (SyntaxError) مواجه میشویم. به مثال زیر دقت کنید:
const color = "Red";
const color = "Blue"; //Uncaught SyntaxError: Identifier 'color' has already been declared
در کد بالا وقتی از کلمه کلیدی const استفاده کنیم، مانند let نمیتوانیم با همان نام تکراری color دوباره آن را تعریف کنیم.
پس var و let در جاوا اسکریپت از لحاظ Redeclaring شبیه هم هستند چون نمیتوان آنها را مجددا با همان نام تکراری تعریف کرد. اما var در جاوا اسکریپت از لحاظ Redeclaring مشکلی ندارد و میتوان هرچند بار که میخواهیم آن را با همان نام مجددا تعریف کنیم.
استفاده از حافظه (RAM)
چهارمین تفاوت var و let و const در جاوا اسکریپت، در اشغال کردن حافظه است. شاید این مورد را کمتر کسی بداند که مصرف حافطه var و let و const چگونه است؟ به مثال زیر توجه کنید:
var firstName = "Reza";
console.log(window.firstName); //Reza
در کد بالا یک متغیر firstName با کلمه کلیدی var تعریف کردهایم و مقدار آن را برابر Reza قرار دادهایم. سپس در خط بعدی console.log(window.firstName) را نوشتهایم، که مقدار آن برابر Reza شده است. در حقیقت وقتی متغیری با کلمه کلیدی var تعریف شود، یک Global Object با همان مقدار در حافظه اشغال میشود (هر چند ناچیز). حال به مثال زیر توجه کنید:
let firstName = "Reza";
console.log(window.firstName); //undefined
وقتی همان متغیر را با کلمه کلیدی let تعریف کنیم، در console.log عبارت undefined را خواهیم دید؛ یعنی چیزی در Global Object، حافظه را اشغال نکرده است. به مثال زیر نیز دقت کنید:
const firstName = "Reza";
console.log(window.firstName); //undefined
اگر با کلمه کلیدی const تعریف کنیم، مانند let با عبارت undefined در کنسول مواجه خواهیم شد؛ یعنی چیزی در Global Object، حافظه را اشغال نکرده است.
پس نتیجه میگیریم که let و const در جاوا اسکریپت، Global Object ذخیره نمیکنند که باعث کاهش مصرف حافظه میشود. اما var در جاوا اسکریپت، یک Global Object در حافظه ذخیره میکند و رم بیشتری نسبت به let و const اشغال میکند.
بالا بردن (Hoisting)
پنجمین تفاوت var و let و const در جاوا اسکریپت، در Hoisting است. Hoisting در لغت به معنی بالا بردن است؛ در اصطلاح برنامه نویسی نیز Hoisting در جاوا اسکریپت به پدیدهای اشاره دارد که در هنگام اجرای کد، تعریف متغیرها و تابعها به بالای بلوک کدی که در آن قرار دارند منتقل میشوند. به این ترتیب، میتوانید از متغیرها و توابع قبل از تعریف آنها استفاده کنید.
به طور معمول، در زبانهای برنامه نویسی، باید متغیرها و توابع را قبل از استفاده از آنها، تعریف کنید (اول تعریف کنید و سپس استفاده کنید). اما در جاوا اسکریپت، به دلیل وجود Hoisting، میتوانید از متغیرها و توابع قبل از تعریف آنها استفاده کنید (اول استفاده کنید و سپس تعریف کنید). به مثال زیر توجه کنید:
console.log(x); // undefined
var x = 5;
در جاوا اسکریپت کدها از خط بالا به پایین اجرا میشود. متغیر x را قبل از تعریف آن در خط اول توسط console.log اجرا میکنیم. سپس در خط دوم متغیر x را با کلمه کلیدی var تعریف میکنیم. قابلیت Hoisting، کد بالا را به کد زیر تفسیر میکند:
var x;
console.log(x); // undefined
x = 5;
یعنی وقتی اول کد را اجرا میکنیم و سپس آن را تعریف میکنیم، متغیر var x بدون مقدار اولیه به بالای برنامه منتقل میشود. سپس در خط دوم اجرا میشود. وقتی یک متغیر بدون مقدار را اجرا کنیم undefined (تعریف نشده) ظاهر خواهد شد.
این به این معنی است که تعریف x به بالای بلوک کد (در این حالت، به بالای برنامه) منتقل شده است، اما مقدار آن هنوز تعیین نشده است. به این ترتیب، درخواست نمایش مقدار x قبل از تعریف آن، به صورت صحیح اجرا میشود. اما در کلمه کلیدی let چطور؟ به مثال زیر توجه کنید:
console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization (TDZ)
let x = 5;
در کلمه کلیدی let، وقتی متغیر x را اول اجرا کنیم و سپس با let تعریف کنیم، با ReferenceError مواجه خواهیم شد. چون قابلیت Hoisting در متغیر let وجود ندارد و تعریف متغیر به بالای برنامه منتقل نمیشود. در نتیجه وقتی متغیری اجرا میکنیم، تعریف متغیر پیدا نمیشود که باعث خطا در برنامه میشود. در کلمه کلیدی const چطور؟ به مثال زیر توجه کنید:
console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization (TDZ)
const x = 5;
در کلمه کلیدی const نیز مانند let، قابلیت Hoisting وجود ندارد. بنابراین تعریف متغیر به اول برنامه منتق نمیشود و با اجرای آن، متغیر پیدا نخواهد شد و با خطای ReferenceError مواجه خواهیم شد.
تلاش برای دسترسی به متغیرها قبل از تعریف آنها باعث خطا در اجرا برای let و const میشود، که به آن Temporal Dead Zone (TDZ) یا «منطقه مرده موقت» میگوییم. TDZ به محدودهای اشاره دارد که در آن متغیرهایی که با استفاده از let و const تعریف شدهاند، اما هنوز قابل دسترسی نیستند. به عبارت دیگر، از زمان شروع اجرا تا اولین لحظه تعریف و مقداردهی اولیه، متغیر در TDZ قرار دارد و تلاش برای دسترسی به آن باعث ایجاد خطا (ReferenceError) میشود.
پس نتیجه میگیریم که var در جاوا اسکریپت، قابلیت Hoisting دارد، بدون خطا اجرا میشود و فقط undefined ظاهر میشود چون مقدار اولیه ندارد. اما let و const در جاوا اسکریپت، قابلیت Hoisting ندارند و چون تعریف متغیر به ابتدای برنامه منتقل نمیشود، پس با اجرای آن، متغیر پیدا نشده و با ReferenceError مواجه خواهیم شد.
محدوده (Scope)
ششمین و مهمترین تفاوت var و let و const در جاوا اسکریپت، در Scope است. Scope به معنی محدوده است یعنی جایی که یک متغیر قابل دسترسی است. متغیر var، به Function Scope معروف است و متغیر let و ثابت const، به Block Scope معروف هستند.
بهطور کلی 3 اسکوپ در جاوا اسکریپت داریم:
- Global Scope: متغیرهایی که بیرون از توابع و بلاکها باشند، از هرجایی (داخل تابع، داخل بلاک و حتی بیرون از آنها) قابل دسترسی هستند.
- Function Scope: متغیرها، داخل توابع (Function) تعریف میشوند و فقط داخل همان تابع قابل دسترسی است. متغیرهای تعریف شده در داخل تابع در بلوکهای دیگر (بیرون آن تابع) قابل دسترسی نیستند. به عبارتی، محدوده قابل دسترسی متغیرها تا محدوده کروشه باز و بسته {} تابعی که در آن تعریف شدهاند، قرار دارد.
- Block Scope: متغیرها داخل بلاکهایی (مانند حلقهها و شرطها) تعریف میشوند و فقط داخل همان بلاک قابل دسترسی است. به عبارتی، محدوده قابل دسترسی متغیرها تا محدوده بلاکی که در آن تعریف شدهاند، محدود است. منظور از بلاک همان داخل حلقهها مانند while ،foreach ،for یا شرط if که محدوده آنها کروشه باز و بسته {} است.
مثال برای Global Scope:
var message1 = "Hello World 1";
let message2 = "Hello World 2";
const message3 = "Hello World 3";
//Function Scope
function sayHello() {
console.log(message1); //Hello World 1
console.log(message2); //Hello World 2
console.log(message3); //Hello World 3
}
//Block Scope
if (true) {
console.log(message1); //Hello World 1
console.log(message2); //Hello World 2
console.log(message3); //Hello World 3
}
//Global Scope
sayHello();
console.log(message1); //Hello World 1
console.log(message2); //Hello World 2
console.log(message3); //Hello World 3
در مثال بالا 3 متغیر با کلمات کلیدی var و let و const در Global Scope (بیرون تابع و بلاک) تعریف کردهایم. حال یک Function با نام ()sayHello داریم و از داخل آن میتوانیم به این متغیرها دسترسی داشته باشیم. حتی از داخل بلاک if نیر میتوانیم به این متغیرها دسترسی داشته باشیم. همچنین از بیرون نیز میتوانیم به این متغیرها دسترسی داشته باشیم. چون هر 3 متغیر در Global Scope تعریف شدهاند و از هرجایی قابل دسترسی هستند.
مثال برای Function Scope:
function sayHello() {
var message = "Hello World!";
console.log(message); //Hello World!
}
sayHello();
console.log(message); //Uncaught ReferenceError: message is not defined
در تابع ()sayHello یک متغیری با نام message داریم که با کلمه کلیدی var تعریف شده است. داخل تابع، یک console.log(message) داریم که عبارت !Hello World را چاپ میکند چون داخل تابع است و دسترسی در محدوده تابع، امکانپذیر است. اما بیرون از تایع وقتی console.log(message) مینویسیم، عبارت !Hello World چاپ نمیشود و با ReferenceError مواجه میشویم چون از بیرون نمیتوانیم به داخل تابع دسترسی داشته باشیم. پس وقتی متغیری با کلمه کلیدی var تعریف شود، Function Scope است و فقط داخل تابع قابل دسترسی است و از بیرون نمیتوان به آن دسترسی داشت.
مثال برای Block Scope:
if (true) {
var message1 = "Hello World 1";
let message2 = "Hello World 2";
const message3 = "Hello World 3";
console.log(message1); //Hello World 1
console.log(message2); //Hello World 2
console.log(message3); //Hello World 3
}
console.log(message1); //Hello World 1
console.log(message2); //Uncaught ReferenceError: message2 is not defined
console.log(message3); //Uncaught ReferenceError: message3 is not defined
در مثال بالا یک بلاک شرطی (if) داریم که داخل آن 3 متغیر با کلمات کلیدی var و let و const تعریف کردهایم. اگر داخل این بلاک هر متغیر را با console.log چاپ کنیم، خروجی آن قابل نمایش است چون داخل همان بلاک قابل دسترسی هستند. اما اگر از بیرون بلاک (if) با console.log بخواهیم خروجی آنها را ببینیم، message1 قابل دسترسی است چون با کلمه کلیدی var تعریف شده و متغیر var، یک Block Scope نیست بلکه Function Scope است پس بلاک را پس میزند و از بیرون به داخل بلاک قابل دسترسی است. اما message2 و message3 با ReferenceError مواجه خواهند شد چون با کلمه کلیدی let و const تعریف شدهاند و Block Scope هستند و از بیرون به داخل بلاک اسکوپ نمیتوانیم دسترسی داشته باشیم.
پس نتیجه میگیریم که متغیر var یک فانکشن اسکوپ است و فقط داخل فانکشن قابل دسترسی است. متغیر let و ثابت const نیز بلاک اسکوپ هستند و فقط داخل بلاک قابل دسترسی هستند. اما نکتهای که باید بدانید این است که اگر متغیر var داخل بلاک باشد، به دلیل بلاک اسکوپ نبودن، میتوان از بیرون به آن دسترسی پیدا کرد. اما اگر متغیر let و ثابت const داخل فانکشن قرار بگیرند، با اینکه بلاک اسکوپ هستند، باز هم از بیرون تابع نمیتوان به آنها دسترسی پیدا کرد. یعنی هم بلاک اسکوپ و هم فانکشن اسکوپ را قبول میکنند.
مشکلات استفاده از var در جاوا اسکریپت چیست؟
در قسمتهای قبل دانستیم که تفاوت var و let و const در جاوا اسکریپت چیست؟ در این قسمت، مشکلات استفاده از var در جاوا اسکریپت را بیان میکنیم. برخی از مشکلات استفاده از var عبارتاند از:
- var، حافظه RAM زیادی نسبت به let و const اشغال میکند (این مورد در بالا بررسی شد).
- Hoisting در var باعث خواهد شد که با undefined روبرو شویم که یک سری مشکلاتی به وجود خواهد آمد مه در let و const وجود ندارد.
- به دلیل Function Scope بودن var یک سری مشکلات به وجود خواهد آمد.
مشکل Hoisting در var
یکی دیگر از مشکلات var، قابلیت Hoisting است، که در قسمت بالا این قابلیت را توضیح اما میخواهیم مشکل Hoisting در var را با مثال بررسی کنیم. به کد زیر توجه کنید:
if (!numProduct) {
console.log("All Products Deleted");
}
var numProduct = 10;
در کد بالا هدف ما این است که متغیر numProduct اگر وجود نداشت (false بود)، شرط ما اجرا شود و تمامی محصولات پاک شوند. اما اگر numProduct وجود داشت (true بود)، شرط اجرا نشود و محصولات حذف نشوند. تعداد محصولات ما 10 عدد (var numProduct = 10) است و محصول وجود دارد. پس انتظار داریم شرط اجرا نشود. اما مشکل کجاست؟
در کد بالا وقتی متغیر numProduct قبل از اینکه تعریف شود، در داخل شرط استفاده شده است. در قسمت Hoisting گفتیم که در متغیر var، نتیجه این کار undefined است و با خطا روبرو نمیشود. undefined در جاوا اسکریپت یک Falsy Value است یعنی مقدار numProduct به دلیل undefined شدن برابر false است. پس معکوس false با علامت ! به true تبدیل شده و شرط اجرا میشود و تمامی محصولات پاک میشوند.
پس numProduct! یعنی اگر محصول وجود نداشت (false بود)، شرط اجرا شود. اما ما 10 محصول داریم و نباید شرط اجرا شود. اما Hoisting در var باعث شده که numProduct با مقدار undefined نتیجه false داشته باشد و محصول نداشته باشیم که باعث اجرای شرط شده و کاملا با برعکس چیزی که انتظار داریم روبرو شویم.
در let و const به دلیل اینکه Hoisting نیستند، وقتی متغیرها قبل از تعریف، اجرا شوند، با خطا روبرو میشویم و برنامه متوقف شده و شروط اجرا نمیشوند.
مشکل Function Scope در var
Function Scope بودن در var باعث یکسری مشکلات در Override خواهد شد. به مثال زیر توجه کنید:
var message = "Hi";
var times = 4;
if (times > 3) {
var message = "Hello";
}
console.log(message); //Hello
در مثال بالا یک متغیر message با مقدار Hi داریم. یک متغیر times هم با مقدار 4 داریم. وقتی شرط (true) برقرار میشود، داخل بلاک if، دوباره یک متغیر message با مقدار Hello تعریف میکنیم. چون متغیر var، یک Block Scope نیست (Function Scope) است، بلاک if را رد میکند و از بیرون میتوان به آن دسترسی داشت در نتیجه متغیر داخل بلاک با تعریف مجدد روی متغیر قبلی Override شده و مقدار آن را از Hi به Hello تغییر میدهد.
مشکل var این است که اگر متغیر message از قبل داخل کدهای ما تعریف شده باشد ولی از وجود آن بیخبر باشیم، احتمال اینکه کد ما دچار باگ شود زیاد است. چون مقدار متغیر جدید، متغیر قبلی را تغییر میدهد. اما در let و const به دلیل Block Scope بودن، وقتی داخل بلاک if قرار بگیرند، داخل همان بلاک قابل دسترسی هستند و مقدار متغیر بیرونی را تغییر نخواهند داد.
خلاصه تفاوت var و let و const در جاوا اسکریپت
در این قسمت، خلاصه تفاوت var و let و const در جاوا اسکریپت که در قسمتهای بالا به آن پرداختیم را بهصورت یکجا معرفی میکنیم:
متغیر var | متغیر let | ثابت const |
میتوان به آن مقدار اولیه نداد. | میتوان به آن مقدار اولیه نداد. | حتما باید مقدار اولیه داشته باشد. |
قابلیت مقداردهی دوباره (تغییر مقدار) دارد. | قابلیت مقداردهی دوباره (تغییر مقدار) دارد. | قابلیت مقداردهی دوباره (تغییر مقدار) ندارد. |
قابلیت تعریف مجدد دارد (متغیرهای var میتوانند دوباره با var تعریف شوند). | قابلیت تعریف مجدد ندارد. | قابلیت تعریف مجدد ندارد. |
متغیر var یک Global Object میسازد و رم بیشتری نسبت به let و const مصرف میکند. | متغیر let یک Global Object نمیسازد. | متغیر const یک Global Object نمیسازد. |
متغیر var، قابلیت Hoisting دارد که باعث میشود مقدار undefined بدهد. | متغیر let، قابلیت Hoisting ندارد. | متغیر let، قابلیت Hoisting ندارد. |
متغیرهای var یا دارای حوزه سراسری (Global Scope) یا حوزه تابعی (Function Scope) هستند. | متغیرهای let دارای حوزه بلاکی (Block Scope) هستند. | ثابتهای const دارای حوزه بلاکی (Block Scope) هستند. |
تفاوت var و let و const در جاوا اسکریپت در یک نگاه
var | let | const | - |
❌ | ❌ | ✅ | اجبار برای مقداردهی اولیه (Initializer) |
✅ | ✅ | ❌ | مقداردهی دوباره (Reassign) |
✅ | ❌ | ❌ | تعریف مجدد (Redeclaring) |
⚠️بیشتر | 🔻کمتر | 🔻کمتر | اشغال کردن حافظه (RAM) |
✅ | ❌ | ❌ | بالا بردن (Hoisting) |
❌ | ✅ | ✅ | Temporal Dead Zone |
✅ | ❌ | ❌ | Function Scope |
❌ | ✅ | ✅ | Block Scope |
چه زمانی از var و let و const در جاوا اسکریپت استفاده کنیم؟
در قسمتهای بالا دانستیم که تفاوت بین var و let و const در جاوا اسکریپت چیست؟ متغیر var از قبل در جاوا اسکریپت وجود داشت اما به دلیل داشتن یک سری مشکلات که در بالا بررسی کردیم، باعث شد که let و const در اکما اسکریپت 6 (ES6) اضافه شوند. اما سوال اصلی اینجاست که چه زمانی باید از var و let و const در جاوا اسکریپت استفاده کنیم؟
- بهطور پیشفرض (Best Practice) همیشه برای تعریف متغیر از const استفاده کنید مگر اینکه بخواهید مقدار آن را در طور برنامه تغییر دهید، در این صورت از let استفاده کنید. یعنی متغیری که در خلال برنامه نباید تغییر کند را با let تعریف نکنید تا از مشکلات override شدن مقدار جدید روی مقدار قبلی جلوگیری کنید.
- var مشکلات زیادی دارد پس سعی کنید برای جلوگیری از باگهای ناخواسته در برنامه، از let به جای var استفاده کنید.
- متغیر var منسوخ نشده است و در جاوا اسکریپت میتوانید از آن استفاده کنید اما یک متغیر غیراستاندارد است و مشکلات زیادی را به بار میآورد. پس بجای استفاده از متغیر var، همیشه از متغیر let و const استفاده کنید.
جمعبندی
تفاوت let ،var و const در جاوا اسکریپت چیست؟ در این مقاله با متغیر var و let و همچنین ثابت const در جاوا اسکریپت آشنا شدیم. در نگاه سطحی، شباهت var و let و const در جاوا اسکریپت وجود دارد. اما در نگاه عمیقتر، تفاوت بین var و let و const در جاوا اسکریپت زیاد است. متغیر var در نسخههای قدیمی جاوا اسکریپت موجود است اما متغیر let و ثابت const در جاوا اسکریپت ES6 معرفی شدهاند. سعی کنید به جای استفاده از متغیر var، از متغیر let استفاده کنید همچنین اگر قرار است مقداری تغییر نکند، از ثابت const استفاده کنید. اگر سوالی در مورد تفاوت var و let و const در جاوا اسکریپت برای شما گنگ است، لطفا در قسمت نظرات با ما در میان بگذارید.