Scope در جاوا اسکریپت مفهومی اساسی است که دسترسی یا قابل مشاهده بودن متغیرها، اشیا و توابع را تعیین میکند. در واقع به وسیله Scope در JavaScript میتوان محدودهای از کدها را تعیین کرد که در آن به متغیر یا تابع دسترسی داریم. ۲ نوع اصلی Scope در زبان برنامه نویسی جاوا اسکریپت وجود دارند که هر کدام از آنها کاربردهای خاص خودشان را دارند. در این مطلب از «مجله تم آف»، بحث Scope در جاوا اسکریپت و انواع آن به همراه مثالهایی با زبان ساده آموزش داده خواهد شد.
Scope در جاوا اسکریپت چیست؟
در محیط جاوا اسکریپت، «Scope» به معنای دامنه (محدوده) کدهای کاربر است. این دامنه به عنوان نوعی تعیین کننده دسترسی به توابع و متغیرها در جاوا اسکریپت عمل میکند. به عبارت سادهتر، تصمیم کاربر در مورد مکان اعلان تابع یا متغیر در جاوا اسکریپت، متعاقباً بر دسترسی آن تأثیر میگذارد. از این رو، وقتی متغیری در تابعی اعلان میشود، تنها در محدوده آن تابع قابل دسترسی است.
- نکته: منظور از کلمات «محدوده» و «دامنه» در این بحث یکسان است. همچنین کلمات «محدوده سراسری» و «محدوده جهانی» نیز مترادف هستند.
انواع Scope در جاوا اسکریپت
اصطلاح Scope در جاوا اسکریپت به معنای دسترسی به متغیرها و توابع در بخشهای خاصی از کدها است. در دنیای برنامه نویسی جاوا اسکریپت، محدوده متغیرها به چند دسته زیر تقسیم میشود:
- «محدوده سراسری» (Global Scope)
- «اسکوپ محلی» (Local Scope)
- «محدوده تابع» (Function Scope)
- «اسکوپ بلوک» (Block Scope)
- «محدوده واژگانی» (Lexical Scope)
در ادامه این آموزش Scope در جاوا اسکریپت، تمامی محدودههای نام برده به همراه مثال آموزش داده خواهند شد.
محدوده سراسری در جاوا اسکریپت چیست؟
متغیرهایی که در ابتدای برنامه اعلان میشوند یا آنهایی که در تابعی محصور نشدهاند، در «محدوده سراسری | جهانی» (Global Scope) قرار میگیرند. اصطلاح Scope در جاوا اسکریپت نشان میدهد که آیا متغیر یا تابع میتواند از قسمتهای مختلف کدها قابل دسترسی باشد یا خیر.
محدوده پیشفرض برای متغیرها و توابع در جاوا اسکریپت، محدوده سراسری است. برای نشان دادن این موضوع، توجه به مثال زیر اهمیت زیادی دارد.
var companion = 'dog';
function displayCompanion() {
console.log(companion); // outputs 'dog' in the console
}
در قطعه کد داده شده، متغیری به نام companion
تعریف شده است. همچنین مقدار dog
به این متغیر اختصاص دارد. همچنین تابعی به نام displayCompanion
اعلان شده که مقدار companion
را در کنسول ثبت میکند. از آنجایی که companion
نوعی متغیر سراسری است، میتوان در تابع displayCompanion
به آن دسترسی ایجاد کرد. به طور مشابه، میتوان به companion
در خارج از تابع دسترسی داشت که خروجی آن به صورت زیر خواهد بود.
console.log(companion); // outputs 'dog' in the console
با این حال، اگر کاربر سعی داشته باشد به متغیری دسترسی پیدا کند که در محدوده جهانی تعریف نشده است، با خطا مواجه خواهد شد.
var companion = 'cat';
function displayCompanion() {
console.log(companion); // outputs 'cat' in the console
}
console.log(otherCompanion); // outputs 'undefined' in the console
در کدهای بالا، متغیری به نام companion
وجود دارد که مقدار cat
به آن اختصاص داده شده است و تابعی به نام displayCompanion
وجود دارد که companion
را ثبت میکند. با این حال، otherCompanion
در محدوده جهانی تعریف نشده و بنابراین دسترسی آن خارج از تابع displayCompanion
تعریف نشده خواهد بود.
console.log(otherCompanion); // outputs 'undefined' in the console
چند مثال از Global Scope در جاوا اسکریپت
در جاوا اسکریپت، زمانی که متغیری در ابتدای «اسکریپت» (Script) یا خارج از هر تابعی اعلان میشود، به عنوان متغیر سراسری در نظر گرفته خواهد شد، به این معنی که میتوان به آن دسترسی داشت و در هر جایی از برنامه از آن استفاده کرد.
در ادامه این مطلب از مجله تم آف چند مثال دیگر برای این نوع محدوده در جاوا اسکریپت آورده شده که مثال اول به صورت زیر است:
// Script to print a message
let greeting = "hello";
function sayHello () {
console.log(greeting);
}
sayHello(); // Outputs: hello
در اسکریپت بالا، greeting
همانطور که در سطح بالای برنامه اعلان شده، نوعی متغییر سراسری محسوب میشود و حتی در تابع sayHello
قابل دسترسی خواهد بود. توجه به این نکته مهم است که مقدار متغیر سراسری را میتوان در تابع تغییر داد. مثال زیر این موضوع را بیان میکند.
// Script to demonstrate change in global variable
let greeting = "hello";
function changeGreeting() {
greeting = 3;
}
// before invoking the function
console.log(greeting);
// after invoking the function
changeGreeting();
console.log(greeting); // Outputs: 3
در کدهای بالا، greeting
نوعی متغیر سراسری به حساب میآید که به صورت hello
مقداردهی شده است. با این حال، در تابع changeGreeting
، مقدار آن به 3
تغییر میکند و این تغییر زمانی که greeting
پس از آن ثبت میشود، منعکس خواهد شد.
نکته حائز اهمیت در اینجا این است که تکیه بر متغیرهای سراسری باید به حداقل برسد، زیرا مقادیر آنها را میتوان در مکانهای مختلف در برنامه تغییر داد که این کار به طور بالقوه منجر به بروز نتایج غیرقابل پیشبینی میشود. جالب اینجاست که در جاوا اسکریپت، متغیر را میتوان بدون اعلان صریح در ابتدا باز هم استفاده کرد. اگر این اتفاق بیفتد، متغیر به طور خودکار دامنه سراسری پیدا میکند. مثال زیر برای بیان این موضوع ارائه شده است.
function sayHello() {
greeting = "hello"
}
sayHello();
console.log(greeting); // Outputs: hello
در این مورد، greeting
نوعی متغیر جهانی محسوب میشود، حتی اگر به صراحت اعلان نشده باشد. اگر متغیر با let greeting = “hello”
اعلان شود، برنامه خطا ایجاد میکند. باید به این نکته توجه داشت که جاوا اسکریپت نوعی «حالت سخت گیرانه» (Strict Mode) ارائه میدهد که در آن متغیر نمیتواند بدون اعلان اولیه استفاده شود.
محدوده محلی در جاوا اسکریپت چیست ؟
مفهوم «محدوده یا دامنه محلی» (Local Scope) به متغیر یا تابعی اشاره دارد که فقط در بلوک کد فعلی آن قابل دسترسی است.
میتوان با استفاده از {}
محدوده محلی ایجاد کرد که مثال زیر این مفهوم را بیان میکند:
{
var companion = 'cat';
}
console.log(companion); // outputs 'undefined' in the console
در قطعه بالا، companion
مقدار cat
را با محدوده محلی ایجاد شده به وسیله {}
اختصاص داده است. با این حال، خارج از {}
نمیتوان به companion
دسترسی پیدا کرد، اما در همان محدوده، قابل دسترسی خواهد بود.
console.log(companion); // outputs 'cat' in the console
مثالی برای Scope محلی در جاوا اسکریپت
در این بخش مثالی برای Scope در جاوا اسکریپت از نوع محلی ارائه میشود. همانطور که گفته شد، متغیر میتواند دارای محدوده محلی باشد، به این معنی که دسترسی به آن فقط به تابعی خاص محدود میشود. مثال زیر برای درک بهتر این مسئله آورده شده است.
// Demonstrating the local scope of a variable
let a = "hello";
function greet() {
let b = "World"
console.log(a + b);
}
greet();
console.log(a + b); // error
Execute Code
//Output
//helloWorld
//Uncaught ReferenceError: b is not defined
در قطعه کد بالا، متغیر a
نوعی متغیر سراسری در نظر گرفته میشود، در حالی که متغیر b
متغیری محلی است. دسترسی به متغیر b
به تابع greet
محدود شده است. در نتیجه، زمانی که تلاشی برای دسترسی به متغیر b
خارج از تابع آن انجام میشود، خطایی ایجاد خواهد شد.
- نکته: همانطور که در تصویر بالا معلوم است، محدوده محلی، خود میتواند شامل ۳ نوع محدوه تابع، محدوه بلوک و محدوده «ماژول» (Module) باشد.
محدوه تابع در جاوا اسکریپت چیست؟
یکی دیگر از انواع Scope در جاوا اسکریپت، «محدوده تابع» (Function Scope) است که محدوده محلی را با تفاوتی کوچک منعکس میکند. در این نوع محدوده، متغیرها و توابعِ تعریف شده در داخل تابع را نمیتوان به صورت سراسری در دسترس قرار داد.
مثال زیر برای درک این نوع محدوده در جاوا اسکریپت مهم است.
function displayCompanion() {
var companion = 'cat';
console.log(companion); // outputs 'cat' in the console
}
در مثال فوق، companion
در displayCompanion
تعریف شده است، از این رو فقط در داخل تابع قابل دسترسی خواهد بود و خارج از تابع، غیر قابل دسترسی است.
console.log(companion); // outputs 'undefined' in the console
محدوده بلوک در جاوا اسکریپت
نوعی دیگری از Scope در جاوا اسکریپت، نوع بلوکی آن یا «محدوده بلوکی» (Block Scope) است. محدوده بلوک کاربر را قادر میسازد تا متغیرها و توابع را منحصراً برای بلوک کد خاصی (هر بخش محصور در {}
) تعریف کند.
میتوان با استفاده از کلمات کلیدی let
یا const
محدوده بلوکی ایجاد کرد. مثال زیر برای درک این مفهوم ضروری است.
let companion = 'cat';
if (true) {
let companion = 'dog';
console.log(companion); // outputs 'dog' in the console
}
console.log(companion); // outputs 'cat' in the console
در قطعه بالا، از let برای تعریف companion
در عبارت if استفاده شده و نوعی محدوده بلوک ایجاد شده است. خارج از بلوک کد سراسری، companion
غیر قابل دسترسی باقی میماند:
console.log(companion); // outputs 'undefined' in the console
- نکته: برای متغیرهای Block Scope در جاوا اسکریپت، محدودهای ایجاد نمیشود.
مثال Block Scope در جاوا اسکریپت
همانطور که بیان شد، کلمه کلیدی let
در جاوا اسکریپت نوعی متغیر با محدوده بلوکی تعریف میکند، به این معنی که متغیر فقط در بلوکی که در آن اعلان شده، قابل دسترسی است.
مثال زیر برای نشان دادن مفهوم محدوده بلوکی برای درک بهتر این موضوع اهمیت زیادی دارد.
// A program demonstrating the block scope notion
// Global variable
let a = 'Hello';
function greet() {
javascript
Copy code
// Local variable
let b = 'World';
console.log(a + ' ' + b);
if (b == 'World') {
// Block-scoped variable
let c = 'hello';
console.log(a + ' ' + b + ' ' + c);
}
// Variable c isn't accessible here
console.log(a + ' ' + b + ' ' + c);
}
greet();
خروجی کدهای بالا به صورت زیر است:
Hello World Hello World hello Uncaught ReferenceError: c is not defined
تشریح کد بالا به صورت زیر است:
- a
متغیری سراسری بوده و در هر جایی از برنامه قابل دسترسی است.
- b
متغیری محلی بوده که فقط در داخل تابع greet
قابل دسترسی است.
- c
متغیری با محدوده بلوک بوده که فقط در بلوک دستور if
قابل دسترسی است.
در برنامه فوق، ۲ اجرای اول console.log()
بدون مشکل اجرا میشوند. با این حال، در سومین فراخوانی console.log()
سعی میشود به متغیر c
با محدوده بلوک در خارج از بلوک آن دسترسی پیدا شود که منجر به خطا خواهد شد.
توجه به این نکته مهم است که در جاوا اسکریپت، در حالی که var
دارای محدوده تابعی است، let
محدوده بلوکی دارد. اگر let c = ‘hello’
با var c = ‘hello’
در عبارت if
جایگزین شود، در نتیجه برنامه با موفقیت اجرا خواهد شد. زیرا c
به عنوان نوعی متغیر محلی در نظر گرفته میشود.
محدوده واژگانی در جاوا اسکریپت
یکی دیگر از انواع Scope در جاوا اسکریپت، «محدوده واژگانی» (Lexical Scope) است. محدوده یا دامنه واژگانی، که همچنین به عنوان «محدوده ایستا» (Static Scope) یا «محدوده کامپایل-زمان» (Compile-Time Scope) نیز شناخته میشود، مفهوم پیچیدهتری است.
این محدوده به وسیله مکان متغیری در کد تعیین میشود، به این معنی که متغیرها در محدوده مشابه متغیرهای والد قابل دسترسی هستند. مثال زیر این مفهوم را بیان میکند.
var companion = 'cat';
function displayCompanion() {
console.log(companion); // outputs 'cat' in the console
}
در مثال فوق، companion
در محدوده سراسری تعریف شده و در displayCompanion
قابل دسترسی است. اما در بلوک کد، companion
قابل دسترسی نیست:
if (true) {
var companion = 'dog';
console.log(companion); // outputs 'dog' in the console
}
console.log(companion); // outputs 'undefined' in the console
در قطعه کد فوق، companion
با استفاده از “var
در داخل عبارت if
تعریف شده و خارج از بلوک کد غیر قابل دسترسی است:
console.log(companion); // outputs 'undefined' in the console
سخن پایانی
مفهوم scope در جاوا اسکریپت بحثی اساسی به حساب میآید که دسترسی به متغیرها و توابع را دیکته میکند. قوانین scope به طور یکنواخت برای متغیرهای const
و let
اعمال میشود، خواه آنها در بلوکی از کدها، تابع یا ماژولی خاص قرار بگیرند. در مقابل، متغیرهای var
تنها زمانی از این قوانین پیروی میکنند که در تابع یا ماژولی قرار گیرند.
استفاده مناسب از Scope در جاوا اسکریپت مزایای مختلفی از جمله افزایش امنیت و پتانسیل استفاده مجدد از کدها را ارائه میدهد. در این مطلب از مجله تم آف بحث Scope در Javascript به صورت نسبتاً کامل بحث شد و انواع این Scopeها به همراه مثالهایی با زبان ساده بحث شدند.