در تمام زبان های برنامه نویسی، میتوانید متغییر تعریف کنید و از آن استفاده کنید. اما در برنامه نویسی جاوا اسکریپت ، شما میتوانید به سه روش متغییرهای خود را تعریف کنید. همیشه این سوال وجود دارد که این روشها چه تفاوتی با هم دارند؟ مزایا و معایب آنها چیست و مخلص کلام: در هر شرایط باید از کدام یک از این روشها برای تعریف متغییرهایمان استفاده کنیم؟ برای گرفتن جواب تمام این سوالات، با من همراه باشید:
Scope چیست؟
در واقع قبل از اینکه به طور مستقیم به بررسی ویژگیهای Var, let و const در برنامه نویسی جاوا اسکریپت بپردازم، باید بدانید اسکوپ چیست؟
اسکوپ به محدودهای گفته میشود که متغییر شما در آن محدوده شناخته شده و در دسترس است.
در برنامه نویسی جاوا اسکریپت، چند نوع اسکوپ داریم: ۱- global scope -2 local scope . خود local scope شامل دو بخش است: ۲٫۱- function scope و ۲٫۲- block scope
در ادامه به بررسی انواع مختلف اسکوپ میپردازم و اینکه هر روش تعریف متغییر در برنامه نویسی جاوا اسکریپت،کدام نوع اسکوپ را در اختیار ما میگذارد.
Global scope
در هر داکیومنت جاوا اسکریپت، تنها یک Global scope (محدوده سراسری) وجود دارد. به محیط خارج محیط تمام توابع، محیط سراسری میگوییم. وقتی متغییری در محیط سراسری تعریف میشود، شما میتوانید در تمام نقاط کد، به آن دسترسی داشته باشید.
اگر یک خیابان با تمام ساختمانهای اطرافش یک داکیومنت باشند، در واقع شاید بتوان خیابان را به یک global scope تشبیه کرد و تمام متغییرهای که در این محیط تعریف میشوند را به وسایل نقلیه عمومی. هر فردی که در خیابان مذکور باشد، میتواند در صورت نیاز از وسایل نقلیه عمومی استفاده کند. دقت کنید این فرد میتواند کنار دکه روزنامه فروشی باشد، یا داخل رستوران یا هر جای دیگر این خیابان(داکیومنت ما). در هر صورت بودن در این خیابان، امکان استفاده از وسیله نقلیه عمومی( متغییری ک در محیط گلوبال تعریف شده است) را برای شخص، فراهم میکند.
اجازه بدهید با یک کد مسئله را بهتر جا بیاندازم:
//global scope
var fruit = 'apple'
console.log(fruit); //apple
function getFruit(){
console.log(fruit); //fruit is accessible here
}
getFruit(); //apple
همانطور که در کد بالا میبینید، متغییر fruit در محیط گلوبال تعریف شده است. ما به این متغییر، در محیط گلوبال و حتی داخل تابع هم دسترسی داریم. هر چند این روش تعریف متغییر به دلیل امنیت پایینش، خیلی توصیه نمیشود، اما شما با این روش تقریبا در تمام زبان های برنامه نویسی میتوانید متغییر تعریف کنید.
باید توجه داشته باشید که در محیط گلوبال، فرقی نمیکند که با کدام روش متغییرتان را تعریف کنید. در نهایت در تمام بخشهای کد به متغییر گلوبال دسترسی خواهید داشت.
Local scope
همانطور که قبلتر گفتم، در برنامه نویسی جاوا اسکریپت، local scope شامل دو بخش است: ۲٫۱- function scope و ۲٫۲- block scope. مفهوم function scope در ECMA script 5 و به کمک var تعریف شد. همچنین block scope که در ECMA script 6 تعریف شد، با کمک let و const پیاده سازی میشود.
برای آشنایی اولیه با local scope ها، به کد زیر توجه کنید:
//global scope
function foo1(){
//local scope 1
function foo2(){
//local scope 2
}
}
//global scope
function foo3(){
//local scope 3
}
//global scope
Function scope
وقتی یک متغییر را در تابع تعریف میکنیم، آن متغییر صرفا در آن تابع در دسترس است و از خارج تابع نمیتوانید به آن متغییر دسترسی داشته باشید. Var این اجازه را به برنامه نویس میدهد تا متغییر را با سطح دسترسی Function scope تعریف کند.
function foo(){
var fruit ='apple';
console.log('inside function: ',fruit);
}
foo(); //inside function: apple
console.log(fruit); //error: fruit is not defined
به کد بالا توجه کنید. متغییر fruit را در تابع تعریف کردیم. بعد از فراخوانی تابع، به دلیل console.log ای که در داخل بدنه تابع وجود دارد، محتوای متغییر fruit در کنسول چاپ میشود.
اما وقتی در global scope سعی کردیم تا fruit را در کنسول چاپ کنیم، ارور رخ میدهد. مثل این میماند بخواهید در وسط خیابان( محیط سراسری) به شیرینیهای داخل شیرینی فروشی دسترسی داشته باشید!
با اینکه var تا حدودی میتواند scope ها را محدود کند، اما خیلی هم موفق نیست! در واقع var یک روش قدیمی و ضعیف( از لحاظ امنیتی) برای تعریف متغییر در برنامه نویسی جاوا اسکریپت است. درصورت نیاز ( گاها هم به صورت تصادفی) میتوانیم متغییری را که با var تعریف کردیم را مجدد مقداردهی(reassign) کنیم و اگر این reassign به طور تصادفی در طول برنامه رخ بدهد، واقعا مشکل ساز خواهد بود.
به کد زیر توجه کنید:
var foo='outside';
if(true){
var foo = 'inside'
console.log(foo); //print inside
}
console.log(foo); //print inside
در کد بالا reassign داخل if ، مقدار متغییر سراسری را نیز تغییر داده است! با اینکه foo را ۲ بار تعریف کردیم ولی انگار یک بار حافظه به آن تخصیص شده است. از دیگر مشکلات var که حسابی برنامه نویس ها را سردرگم میکند میتوان به استفاده قبل از تعریف اشاره کرد! ( برنامه نویس های مبتدی واقعا در این مرحله سردرگم میشوند)
به کد زیر توجه کنید:
var x = 'foo';
console.log(x); //foo
console.log(y); //undefined, no errors!!
var y = 'late foo'; //late foo
console.log(y);
در واقع ما متغییر y را قبل از تعریف و مقدار دهی،چاپ کردهایم. موتور جاوا اسکریپت در این موارد خطا نمیدهد بلکه undefined چاپ میکند. علت این است که موتور جاوا اسکریپت موقع تفسیر کد، ابتدا تمام تعریف متغییرها در داکیومنت را بررسی و در memory برایشان حافظه تخصیص میدهد. تعریف متغییرها(Variable declaration) نه مقدارشان(value). پس موقعی که موتور جاوا اسکریپت میخواهد y را چاپ کند، در واقع از قبل برای y در مموری حافظهای وجود دارد که مقدار آن مشخص نیست. پس خطایی هم در کار نیست!
Block scope
بلاک اسکوپ به محیط داخل شروط if, switch case یا داخل حلقههای for یا while میگویند. در واقع {…….} یا همان براکت باز و بسته یک بلاک است (مهم نیست این براکت در کنار کدوم keyword میآید). در ES6 کلمات کلیدی let و const این اجازه را به برنامه نویس میدهند که متغییری در محیط بلاک تعریف کند. این نوع متغییرها صرف و صرفا در همان Block scopeای که در آن تعریف شدهاند، در دسترس و قابل استفادهاند.
به کد زیر توجه کنید:
function foo(){
if(true){
var fruit1 = 'apple'; //exist in function scope
const fruit2 = 'banana'; //exist in block scope
let fruit3 = 'strawberry'; //exist in block scope
}
console.log(fruit1);
console.log(fruit2);
console.log(fruit3);
}
foo();
//result:
//apple
//error: fruit2 is not defined
//error: fruit3 is not defined
در کد بالا یک بلاک if را داخل یک تابع قراردادهام. در این بلاک ۳ متغییر با سه روش let, var و const تعریف کردهام و داخل تابع سعی دارم که مقادیر متغییرها را در کنسول چاپ کنم. موقع فراخوانی تابع، صرفا متغییری که با var تعریف شده است، در کنسول چاپ میشود. علت چیست؟ چون متغییر fruit1 با var تعریف شدهاست، بنابراین علاوه بر اینکه در محدوده بلاک به آن دسترسی داریم، در محدوده تابع هم در دسترس است. برعکس دو متغییر دیگر صرفا در داخل بلاک if در دسترس هستند. سعی کنید چاپ fruit2 و fruit3 را داخل if بگذارید. نتیجه را با نتیجه فعلی مقایسه کنید.
خب همانطور که دیدید let و const هر دو محیط بلاک را در اختیار ما میگذارند. پس این سوال پیش میآید که این دو روش تعریف متغییر در برنامه نویس جاوا اسکریپت، چه تفاوتی با هم دارند؟
Const زمانی استفاده میشود که بخواهید متغییری تعریف کنید که امکان reassign کردن نداشته باشد. این به معنای تغییرناپذیر بودن متغییرهای تعریف شده با const نیست!
به کد زیر توجه کنید:
const user = {
firstName:"Ali",
lastName:"Alavi"
};
user = {firstName: "Elham",lastName: "Bigdeli"}; //error
console.log(user);
user.firstName="Elham";
user.lastName="Bigdeli";
console.log(person); //it's ok
ما نمیتوانیم مجددا متغییر user را مقداردهی کنیم. اما میتوانیم آن را در سطح property هایش، تغییر دهیم. شاید بتوان گفت const برای تعریف متغییرهایی که یک مقدار دیفالت باید داشته باشند، گزینه مناسبی است.
Let اما برعکس const امکان مقداردهی مجدد را به ما میدهد.
به کد زیر توجه کنید:
let foo='outside';
if(true){
let foo = 'inside'
console.log(foo); //print inside
}
console.log(foo); //print outside
در مثال بالا به دلیل اینکه let در محدوده بلاک در دسترس است، مقدار دو متغییر که هم نام هستند، اما در بلاک های متفاوتی تعریف شدهاند، متفاوت است. از طرفی امکان reassign کردن متغییر هم فراهم است.
در این مقاله تمام سعیام بر این بود که تفاوتVar, let و const در برنامه نویسی جاوا اسکریپت را با مثالهای ملموس برایتان توضیح دهم. امیدوارم به هدفم رسیده باشم.
اگر سوال یا نظری درباره تفاوتVar, let و const در برنامه نویسی جاوا اسکریپت دارید، با من و سایر خوانندگان این مقاله در میان بگذارید. تا یادم نرفته، بنظر شما مقالهی بعدی دربارهی چه موضوعی باشد؟
راستی! تلگرام چ یاب رو برای با خبر شدن از آخرین دورههای آموزشی، محصولات و تخفیف های ویژه دنبال کنید.
منابع: dev.to
ارسال پاسخ
نمایش دیدگاه ها