درک بهتر Scope در جاوااسکریپت یکی از قسمتهای مهم یادگیری این زبان برنامه نویسی است. مفهوم Scope به معنی میزان دسترسی به متغیرها در توابع، آبجکتها و بلاکهای کد است.
برای مزایای استفاده از Scope میتوان به این موارد اشاره کرد:
امنیت. متغیرها و توابع فقط زمانی قابل دسترسی هستند که به آنها نیاز داریم.
کمتر شدن تداخل در Namespaceها. تداخل Namespace زمانی اتفاق میافتد که برای دو متغیر متفاوت از یک نام استفاده میکنیم. Scope در متغیرها کمک میکند که استفاده از متغیرهای سراسری کمتر شود. در نتیجه برای تعریف نام متغیرها آزادی عمل بیشتری خواهیم داشت.
قابلیت استفاده مجدد از کدها. استفاده صحیح از متغیرهای محلی باعث توسعه سادهتر و قابلیت استفاده مجدد میشود.
به طور کلی در زبان برنامه نویسی جاوااسکریپت دو نوع Scope داریم. Scopeهای سراسری و محلی. همین طور در این مطلب و ویدیوی آموزشی به طور دقیق Lexical Scope و Block Scope را نیز بررسی خواهیم کرد.
زمانی که توسعه کدهای جاوااسکریپت را شروع میکنیم، در Scope یا Global Scope هستیم.
تمام کدهایی که در Scope سراسری توسعه میدهیم، مانند توابع، متغیرها و… در قسمتهای مختلف برنامه قابل دسترسی هستند. چرخه حیات متغیرهای سراسری، کاملا وابسته به برنامه اصلی است. به این معنی که اگر برنامه بسته شود، متغیرها هم دیگر قابل استفاده نیستند.
با توجه به این موضوع، استفاده زیاد از متغیرهای سراسری کار منطقیای نیست. تعریف بیش از اندازه متغیرهای سراسری باعث میشود کد برنامه کمتر قابلیت استفاده مجدد را داشته باشد. تا حد امکان این استفاده باید مدیریت شده باشد.
مقادیر محلی در برنامه فقط در جایی قابل دسترسی هستند که تعریف شدهاند. سادهترین راه تعریف یک Scope محلی، توسعه یک تابع است. در جاوااسکریپت هر تابعی که نوشته میشود، یک Scope محلی ایجاد میکند. داخل توابع هر متغیری که تعریف شود، به عنوان متغیر محلی در نظر گرفته خواهد شد. طبیعتا متغیرهای محلی فقط در همان Scope قابلیت دسترسی دارند.
این مثال را بررسی کنید:
var cat = 'Jerry'; console.log(cat); // Jerry function localScopeExample(){ var dog = 'Marley'; console.log(cat); // Jerry } console.log(cat); // Jerry
در این مثال دو متغیر داریم. متغیر cat در Scope سراسری تعریف شده، پس در تمام قسمتهای برنامه قابل دسترسی است. متغیر دیگر ما که dog است، در تابع localScopeExample تعریف شده. این متغیر را فقط در Scope محلی میتوان استفاده کرد. اگر بیرون Scope آن را فراخوانی کنیم، برنامه با خطا مواجه خواهد شد.
اگر از متغیر dog در Scope سراسری استفاده کنیم، خطای Uncaught ReferenceError را خواهیم دید.
آخرین نکته در استفاده از Scopeهای محلی. این متغیرهای به صورت محلی در توابع تعریف شدهاند. در نتیجه میتوانیم از یک نام برای تعریف متغیرهای محلی در توابع مختلف استفاده کنیم.
function func1(){ var dog = 'Marley'; console.log(dog); // Marley } function func2(){ var dog = 'Shasta'; console.log(dog); // Shasta }
Lexical Scope یا Static Scope به معنی توانایی دسترسی تابع داخلی به مقادیر یک تابع اصلی است. این مثال را بررسی کنید:
// *GLOBAL* var dog = 'Lewis'; function outerFunc(){ // *SCOPE 1* var cat = 'Jerry'; function innerFunc(){ // *SCOPE 2* console.log(cat); // Jerry console.log(dog); // Lewis } }
در این کد تابع outerFunc به عنوان مقدار Scope سراسری تعریف شده. همین طور تابع innerFunc در داخل Scope تابع outerFunc استفاده شده. به خاطر مفهوم Lexical Scope تمام قسمتهای Scope2 دسترسی به متغیرها در Scope1 را دارند.
تا اینجا برای تعریف تمام متغیرها از دستور var استفاده کردیم. زمانی که از دستور var استفاده میکنیم، تنها توابع به عنوان یک Scope در نظر گرفته میشوند. اما Block Scopeهای دیگر مانند دستورات if ،for و while تاثیری بر روی var ندارند.
دستورات let و const در نسخههای جدید جاوااسکریپت ارایه شدند. تعریف مقادیر با این دستورات باعث میشود تا تمام Blockها به عنوان یک Scope در نظر گرفته شوند.
let x = 1; { let x = 2; console.log(x); // 2 } console.log(x); // 1
همین طور که مشاهده میکنید، استفاده از bracket باعث شده تا بتوانیم متغیر محلی داشته باشیم. با این که به نظر میرسد ما فقط یک متغیر x داریم، اما اینطور نیست. یکی از متغیرها با مقدار ۱ به عنوان متغیر سراسری تعریف شده. متغیر دیگر با مقدار ۲ یک متغیر محلی است.
جاوااسکریپت در زمان تفسیر، ابتدا متغیرهای داخلی را پردازش میکند. اگر متغیری را پیدا نکند، به ترتیب Blockهای بیرونی را پردازش خواهد کرد.
دقیقا همین موضوع برای سایر Block Scopeها مانند if ،for و while نیز وجود دارد.
let x = 1; if (x !== 2) { let x = 2; console.log(x); // 2 } console.log(x); // 1
توجه داشته باشید که شما نمیتوانید متغیرهای هم نام را در یک Block مشخص تعریف و استفاده کنید.
{ let x = 1; let x = 2; } Uncaught SyntaxError: Identifier 'x' has already been declared
امیدواریم که این مقاله برای شما مفید بوده باشد. برای دیدن ویدیوهای آموزشی یک قسمتی فرانت کست، میتوانید کانال یوتوب فرانت کست را دنبال کنید.