Scope در جاوا اسکریپت چیست؟ – توضیح به زبان ساده + مثال و کد
Scope در جاوا اسکریپت مفهومی اساسی است که دسترسی یا قابل مشاهده بودن متغیرها، اشیا و توابع را تعیین میکند. در واقع به وسیله Scope در JavaScript میتوان محدودهای از کدها را تعیین کرد که در آن به متغیر یا تابع دسترسی داریم. ۲ نوع اصلی Scope در زبان برنامه نویسی جاوا اسکریپت وجود دارند که هر کدام از آنها کاربردهای خاص خودشان را دارند. در این مطلب از «مجله فرادرس»، بحث Scope در جاوا اسکریپت و انواع آن به همراه مثالهایی با زبان ساده آموزش داده خواهد شد.
Scope در جاوا اسکریپت چیست؟
در محیط جاوا اسکریپت، «Scope» به معنای دامنه (محدوده) کدهای کاربر است. این دامنه به عنوان نوعی تعیین کننده دسترسی به توابع و متغیرها در جاوا اسکریپت عمل میکند. به عبارت سادهتر، تصمیم کاربر در مورد مکان اعلان تابع یا متغیر در جاوا اسکریپت، متعاقباً بر دسترسی آن تأثیر میگذارد. از این رو، وقتی متغیری در تابعی اعلان میشود، تنها در محدوده آن تابع قابل دسترسی است.
- نکته: منظور از کلمات «محدوده» و «دامنه» در این بحث یکسان است. همچنین کلمات «محدوده سراسری» و «محدوده جهانی» نیز مترادف هستند.
انواع Scope در جاوا اسکریپت
اصطلاح Scope در جاوا اسکریپت به معنای دسترسی به متغیرها و توابع در بخشهای خاصی از کدها است. در دنیای برنامه نویسی جاوا اسکریپت، محدوده متغیرها به چند دسته زیر تقسیم میشود:
- «محدوده سراسری» (Global Scope)
- «اسکوپ محلی» (Local Scope)
- «محدوده تابع» (Function Scope)
- «اسکوپ بلوک» (Block Scope)
- «محدوده واژگانی» (Lexical Scope)
در ادامه این آموزش Scope در جاوا اسکریپت، تمامی محدودههای نام برده به همراه مثال آموزش داده خواهند شد.
محدوده سراسری در جاوا اسکریپت چیست؟
متغیرهایی که در ابتدای برنامه اعلان میشوند یا آنهایی که در تابعی محصور نشدهاند، در «محدوده سراسری | جهانی» (Global Scope) قرار میگیرند. اصطلاح Scope در جاوا اسکریپت نشان میدهد که آیا متغیر یا تابع میتواند از قسمتهای مختلف کدها قابل دسترسی باشد یا خیر.
محدوده پیشفرض برای متغیرها و توابع در جاوا اسکریپت، محدوده سراسری است. برای نشان دادن این موضوع، توجه به مثال زیر اهمیت زیادی دارد.
1var companion = 'dog';
2function displayCompanion() {
3 console.log(companion); // outputs 'dog' in the console
4}
در قطعه کد داده شده، متغیری به نام companion تعریف شده است. همچنین مقدار dog به این متغیر اختصاص دارد. همچنین تابعی به نام displayCompanion اعلان شده که مقدار companionرا در کنسول ثبت میکند. از آنجایی که companionنوعی متغیر سراسری است، میتوان در تابعdisplayCompanionبه آن دسترسی ایجاد کرد. به طور مشابه، میتوان به companionدر خارج از تابع دسترسی داشت که خروجی آن به صورت زیر خواهد بود.
1console.log(companion); // outputs 'dog' in the console
با این حال، اگر کاربر سعی داشته باشد به متغیری دسترسی پیدا کند که در محدوده جهانی تعریف نشده است، با خطا مواجه خواهد شد.
1var companion = 'cat';
2function displayCompanion() {
3 console.log(companion); // outputs 'cat' in the console
4}
5console.log(otherCompanion); // outputs 'undefined' in the console
در کدهای بالا، متغیری به نامcompanionوجود دارد که مقدار cat به آن اختصاص داده شده است و تابعی به نام displayCompanionوجود دارد که companionرا ثبت میکند. با این حال، otherCompanion در محدوده جهانی تعریف نشده و بنابراین دسترسی آن خارج از تابع displayCompanionتعریف نشده خواهد بود.
1console.log(otherCompanion); // outputs 'undefined' in the console
چند مثال از Global Scope در جاوا اسکریپت
در جاوا اسکریپت، زمانی که متغیری در ابتدای «اسکریپت» (Script) یا خارج از هر تابعی اعلان میشود، به عنوان متغیر سراسری در نظر گرفته خواهد شد، به این معنی که میتوان به آن دسترسی داشت و در هر جایی از برنامه از آن استفاده کرد.
در ادامه این مطلب از مجله فرادرس چند مثال دیگر برای این نوع محدوده در جاوا اسکریپت آورده شده که مثال اول به صورت زیر است:
1// Script to print a message
2let greeting = "hello";
3
4function sayHello () {
5 console.log(greeting);
6}
7
8sayHello(); // Outputs: hello
در اسکریپت بالا، greeting همانطور که در سطح بالای برنامه اعلان شده، نوعی متغییر سراسری محسوب میشود و حتی در تابع sayHello قابل دسترسی خواهد بود. توجه به این نکته مهم است که مقدار متغیر سراسری را میتوان در تابع تغییر داد. مثال زیر این موضوع را بیان میکند.
1// Script to demonstrate change in global variable
2let greeting = "hello";
3
4function changeGreeting() {
5 greeting = 3;
6}
7
8// before invoking the function
9console.log(greeting);
10
11// after invoking the function
12changeGreeting();
13console.log(greeting); // Outputs: 3
در کدهای بالا، greetingنوعی متغیر سراسری به حساب میآید که به صورت hello مقداردهی شده است. با این حال، در تابع changeGreeting ، مقدار آن به 3 تغییر میکند و این تغییر زمانی که greetingپس از آن ثبت میشود، منعکس خواهد شد.
نکته حائز اهمیت در اینجا این است که تکیه بر متغیرهای سراسری باید به حداقل برسد، زیرا مقادیر آنها را میتوان در مکانهای مختلف در برنامه تغییر داد که این کار به طور بالقوه منجر به بروز نتایج غیرقابل پیشبینی میشود. جالب اینجاست که در جاوا اسکریپت، متغیر را میتوان بدون اعلان صریح در ابتدا باز هم استفاده کرد. اگر این اتفاق بیفتد، متغیر به طور خودکار دامنه سراسری پیدا میکند. مثال زیر برای بیان این موضوع ارائه شده است.
1function sayHello() {
2 greeting = "hello"
3}
4
5sayHello();
6
7console.log(greeting); // Outputs: hello
در این مورد، greetingنوعی متغیر جهانی محسوب میشود، حتی اگر به صراحت اعلان نشده باشد. اگر متغیر با let greeting = "hello" اعلان شود، برنامه خطا ایجاد میکند. باید به این نکته توجه داشت که جاوا اسکریپت نوعی «حالت سخت گیرانه» (Strict Mode) ارائه میدهد که در آن متغیر نمیتواند بدون اعلان اولیه استفاده شود.
محدوده محلی در جاوا اسکریپت چیست ؟
مفهوم «محدوده یا دامنه محلی» (Local Scope) به متغیر یا تابعی اشاره دارد که فقط در بلوک کد فعلی آن قابل دسترسی است.
میتوان با استفاده از {} محدوده محلی ایجاد کرد که مثال زیر این مفهوم را بیان میکند:
1{
2 var companion = 'cat';
3}
4console.log(companion); // outputs 'undefined' in the console
در قطعه بالا، companion مقدار cat را با محدوده محلی ایجاد شده به وسیله {}اختصاص داده است. با این حال، خارج از{}نمیتوان به companionدسترسی پیدا کرد، اما در همان محدوده، قابل دسترسی خواهد بود.
1console.log(companion); // outputs 'cat' in the console
مثالی برای Scope محلی در جاوا اسکریپت
در این بخش مثالی برای Scope در جاوا اسکریپت از نوع محلی ارائه میشود. همانطور که گفته شد، متغیر میتواند دارای محدوده محلی باشد، به این معنی که دسترسی به آن فقط به تابعی خاص محدود میشود. مثال زیر برای درک بهتر این مسئله آورده شده است.
1// Demonstrating the local scope of a variable
2let a = "hello";
3
4function greet() {
5let b = "World"
6console.log(a + b);
7}
8
9greet();
10console.log(a + b); // error
11Execute Code
12//Output
13
14//helloWorld
15//Uncaught ReferenceError: b is not defined
در قطعه کد بالا، متغیر a نوعی متغیر سراسری در نظر گرفته میشود، در حالی که متغیر b متغیری محلی است. دسترسی به متغیر bبه تابع greet محدود شده است. در نتیجه، زمانی که تلاشی برای دسترسی به متغیر bخارج از تابع آن انجام میشود، خطایی ایجاد خواهد شد.
- نکته: همانطور که در تصویر بالا معلوم است، محدوده محلی، خود میتواند شامل ۳ نوع محدوه تابع، محدوه بلوک و محدوده «ماژول» (Module) باشد.