در این مقاله، با scope و نحوه عملکرد آن در جاوا اسکریپت آشنا خواهید شد.
Scope یک مفهوم اساسی در جاوا اسکریپت و سایر زبان های برنامه نویسی است که زمینه دسترسی و استفاده از متغیرها را تعریف می کند. با ادامه یادگیری جاوا اسکریپت و کار بیشتر با متغیرها، برای کد شما مفیدتر و کاربردی تر می شود.
Scope می تواند به شما کمک کند:
- استفاده کارآمدتر از حافظه: Scope توانایی بارگذاری متغیرها را فقط در صورت نیاز فراهم می کند. اگر متغیری خارج از محدوده است، نیازی نیست آن را برای کدی که در حال اجرا است در دسترس قرار دهید.
- باگها را راحتتر بیابید و برطرف کنید: جداسازی متغیرها با محدوده محلی، عیبیابی باگها را در کدتان آسانتر میکند، زیرا بر خلاف متغیرهای سراسری، میتوانید اعتماد کنید که کد از محدوده بیرونی نمیتواند متغیرهای محدوده محلی را دستکاری کند.
- ایجاد بلوک های کوچک از کدهای قابل استفاده مجدد: به عنوان مثال، می توانید یک تابع خالص بنویسید که به محدوده بیرونی متکی نباشد. شما به راحتی می توانید چنین عملکردی را با حداقل تغییرات به جای دیگری منتقل کنید.
دامنه چیست؟
محدوده یک متغیر تعیین می کند که از کجا در کد می توانید از یک متغیر استفاده کنید.
جاوا اسکریپت متغیرهایی با دامنه جهانی یا محلی را تعریف می کند:
- متغیرهای با دامنه جهانی از همه دامنه های دیگر در کد جاوا اسکریپت در دسترس هستند.
- متغیرهای با دامنه محلی فقط در یک زمینه محلی خاص در دسترس هستند و توسط کلمات کلیدی مانند
var
،let
وconst
ایجاد میشوند. اگر از کلمات کلیدیvar
،let
یاconst
برای ایجاد یک متغیر در یک تابع استفاده کنید، آن متغیر دارای محدوده محلی است.
بخشهای بعدی این مقاله به بحث بلوک و دامنه واژگانی میپردازد:
- متغیرهای محدوده بلوک به صورت محلی برای یک بلوک در دسترس هستند که توسط مکان براکت های فرفری که در آن دستور بلوک تعریف می شود تعیین می شود. فقط متغیرهای اعلام شده با کلمات کلیدی
let
یاconst
دارای محدوده بلاک هستند. - دامنه واژگانی از مکانی استفاده می کند که یک متغیر در کد منبع اعلام شده است تا مشخص کند آن متغیر کجا در دسترس است. شما از بسته ها استفاده می کنید تا به یک تابع محصور دسترسی به متغیرهای ارجاع داده شده در محدوده بیرونی به نام محیط واژگانی را بدهید.
هنگامی که یک متغیر در محدوده آن قابل دسترسی است، جاوا اسکریپت مقدار اختصاص داده شده آن را برمی گرداند یا در غیر این صورت یک خطا ایجاد می کند.
برای تعریف یک متغیر:
- از کلمات کلیدی
var
،const
یاlet
برای اعلام متغیرهای محلی یا جهانی استفاده کنید. - از کلمات کلیدی
const
یاlet
برای اعلام متغیرهای محدوده بلوک استفاده کنید.
هنگامی که یک متغیر var
را در یک تابع اعلام می کنید، این اعلان متغیر را در دسترس نزدیکترین تابع محصور قرار می دهد. شما نمی توانید از کلمه کلیدی var
برای اعلام متغیرهایی با محدوده بلاک استفاده کنید.
نمونه های دامنه
این مثال دامنه جهانی را نشان می دهد زیرا متغیر greeting
خارج از هر تابع یا بلوک اعلان شده است، که باعث می شود مقدار آن برای همه کدهای سند جاری در دسترس باشد:
const greeting = 'hello';
console.log(greeting); // 'hello'
در مثال جهانی، به متغیر greeting
یک مقدار hello
اختصاص داده می شود.
این مثال محدوده محلی را نشان می دهد زیرا متغیر greeting
با کلمه کلیدی let
در یک تابع اعلام می کند. متغیر greeting
یک متغیر با محدوده محلی است و خارج از تابع در دسترس نیست.
function greet() {
let greeting = 'Hello World!';
console.log(greeting);
}
این مثال محدوده بلوک را نشان می دهد زیرا متغیر greeting
را در یک بلوک اعلام می کند به طوری که متغیر فقط در داخل براکت های فرفری قابل دسترسی است:
if (true) {
const greeting = 'hello';
}
console.log(greeting); // ReferenceError: greeting is not defined
توجه داشته باشید که وقتی تابع console.log
سعی می کند مقدار متغیر greeting
را خروجی دهد، جاوا اسکریپت یک پیغام خطای ReferenceError
را به جای پیام hello
مورد انتظار برمی گرداند. چرا؟
یک خطا برگردانده می شود زیرا متغیر greeting
دارای محدوده بلوک است و نزدیکترین بلوک بخشی از عبارت شرطی if
است. شما نمی توانید از خارج از بلوک به متغیرهای let
و const
که در داخل یک بلوک اعلام می کنید دسترسی داشته باشید. بنابراین، شما فقط میتوانید به متغیر greeting
در براکتهای فرفری دسترسی داشته باشید، که محدوده بلوک را مشخص میکند.
این مثال خطا را برطرف میکند زیرا متد console.log(message)
به داخل براکتهای فرفری منتقل میکند. کد به روز شده، متد console.log(message)
را در داخل بلوک جابجا می کند.
if (true) {
const greeting = 'hello';
console.log(greeting);
}
انواع دامنه
گستره جهانی
شما می توانید از هر جای برنامه به متغیرهایی با دامنه جهانی دسترسی داشته باشید.
یک فایل HTML را در نظر بگیرید که دو فایل جاوا اسکریپت را وارد می کند: file-1.js
و file-2.js
:
<script src="file-1.js"></script>
<script src="file-2.js"></script>
در این مثال، متغیر globalMessage
دارای یک دامنه جهانی است و خارج از یک تابع نوشته شده است. در حین اجرا و اجرا، می توانید از هر نقطه ای از برنامه جاوا اسکریپت به مقدار متغیر globalMessage
دسترسی داشته باشید.
شما می توانید محتویات فایل های file-1.js
و file-2.js
در این قطعه کد مشاهده کنید. به در دسترس بودن متغیر globalMessage
در هر دو فایل توجه کنید.
// file-1.js
function hello() {
var localMessage = 'Hello!';
}
var globalMessage = 'Hey there!';
// file-2.js
console.log(localMessage); // localMessage is not defined
console.log(globalMessage); // Hey there!
نوع دیگری از دامنه وجود دارد که در این مقاله به شدت مورد بحث قرار نگرفته است. اگر متغیری را در یک ماژول جاوا اسکریپت ایجاد کنید اما خارج از یک تابع یا بلوک، این متغیر دارای دامنه جهانی نیست، بلکه دامنه ماژول را دارد. متغیرهای با دامنه ماژول در هر جایی در ماژول فعلی موجود هستند، اما از فایلها یا ماژولهای دیگر در دسترس نیستند. برای در دسترس قرار دادن یک متغیر با دامنه ماژول برای فایلهای دیگر، باید آن را از ماژولی که در آن ایجاد شده صادر کنید و سپس آن را از ماژولی که نیاز به دسترسی به متغیر دارد وارد کنید .
محدوده محلی و محدوده عملکرد
هنگامی که متغیرهایی را در یک تابع جاوا اسکریپت با کلمات کلیدی var
، let
یا const
ایجاد می کنید، متغیرها محلی برای تابع هستند، بنابراین شما فقط می توانید از داخل تابع به آنها دسترسی داشته باشید. متغیرهای محلی هنگام شروع یک تابع ایجاد می شوند و با پایان اجرای عملکرد به طور موثر حذف می شوند.
این مثال متغیر total
را در تابع addNumbers()
اعلام می کند. شما فقط می توانید به متغیرهای a
، b,
و total
در تابع addNumbers()
دسترسی داشته باشید.
function addNumbers(a, b) {
const total = a + b;
}
addNumbers(3, 4);
برای نامگذاری متغیرها می توانید از کلمات کلیدی let
و const
استفاده کنید. هنگامی که از کلمه کلیدی let
استفاده می کنید، جاوا اسکریپت می تواند متغیر را به روز کند. با این حال، با کلمه کلیدی const
، متغیر ثابت می ماند.
var variable1 = 'Declared with var';
var variable1 = 'Redeclared with var';
variable1; // Redeclared with var
let variable2 = 'Declared with let. Cannot be redeclared.';
variable2 = 'let cannot be redeclared, but can be updated';
variable2; // let cannot be redeclared, but can be updated
const variable3 = 'Declared with const. Cannot be redeclared or updated';
variable3; // Declared with const. Cannot be redeclared or updated
محدوده را مسدود کنید
بلوک ها برای گروه بندی یک عبارت واحد یا مجموعه ای از عبارات با هم استفاده می شوند. می توانید از کلمات کلیدی const
یا let
برای اعلام یک متغیر محلی block-scope استفاده کنید. توجه داشته باشید که نمی توانید از کلمه کلیدی var
برای اعلام متغیرهایی با محدوده بلاک استفاده کنید.
به عنوان مثال، در این بلوک، محدوده متغیر name
و مقدار "Elizabeth"
آن در داخل پرانتزهای فرفری قرار دارد. متغیرهای درون محدوده بلوک خارج از بلوک در دسترس نیستند.
{
const name = "Elizabeth";
}
میتوانید از متغیرهای محدوده بلوک در عبارات if
، for
یا while
استفاده کنید.
به دو حلقه for
در این قطعه کد توجه کنید. حلقه for
از کلمه کلیدی var
برای اعلام متغیر اولیه استفاده می کند که از طریق اعداد 0
، 1
و 2
افزایش می یابد. حلقه for
دیگر از کلمه کلیدی let
برای اعلام متغیر اولیه استفاده می کند.
for (var i = 0; i < 2; i++) {
// ...
}
console.log(i); // 2
for (let j = 0; j < 2; j++) {
// ...
}
console.log(j); // The j variable isn't defined.
در مثال کد قبلی، ممکن است متوجه شوید که متغیر i
در اولین حلقه for
به بیرون از حلقه for
نشت می کند و همچنان مقدار 2
را حفظ می کند زیرا کلمه کلیدی var
از محدوده بلوک استفاده نمی کند. این مشکل در دومین حلقه for
حل شده است که در آن متغیر j
با کلمه کلیدی let
در بلوک حلقه for
قرار می گیرد و پس از اتمام حلقه for
وجود ندارد.
استفاده مجدد از نام متغیر در محدوده متفاوت
Scope میتواند یک متغیر را در یک تابع جدا کند، حتی زمانی که از نام متغیر مشابه در جای دیگری در محدوده متفاوتی استفاده میکنید.
این مثال به شما نشان می دهد که چگونه استفاده از scope به شما امکان می دهد از نام متغیر مشابه در توابع مختلف استفاده مجدد کنید:
function listOne() {
let listItems = 10;
console.log(listItems); // 10
}
function listTwo() {
let listItems = 20;
console.log(listItems); // 20
}
listOne();
listTwo();
به متغیرهای listItems
در توابع listOne()
و listTwo()
مقادیر مورد انتظار اختصاص داده می شود و بنابراین با یکدیگر تداخل ندارند.
بسته ها و دامنه واژگانی
بسته ها به یک تابع محصور اطلاق می شود که در آن یک تابع درونی می تواند به محدوده عملکرد بیرونی دسترسی پیدا کند که به عنوان محیط واژگانی نیز شناخته می شود. بنابراین، در جاوا اسکریپت، شما از بستهها استفاده میکنید تا به توابع اجازه دهید به محیط واژگانی بیرونی ارجاع دهند، که اجازه میدهد کد داخل تابع، متغیرهای خارج از تابع را ارجاع دهد. در واقع، میتوانید زنجیرهای از ارجاعات به محیطهای واژگانی بیرونی را کدنویسی کنید تا یک تابع توسط یک تابع فراخوانی شود که به نوبه خود توسط تابع دیگری فراخوانی میشود.
در این مثال، کد با محیط واژگانی که هنگام فراخوانی تابع outer()
ایجاد میشود، بسته میشود که روی متغیر hello
بسته میشود. بنابراین، متغیر hello
در تابع callback setTimeout
استفاده می شود.
function outer() {
const hello = 'world';
setTimeout(function () {
console.log('Within the closure!', hello)
}, 100);
}
outer();
با دامنه واژگانی، دامنه در طول کامپایل کد منبع تعیین می شود، نه در زمان اجرا. برای کسب اطلاعات بیشتر در مورد محیط واژگانی، به محدوده واژگانی و بسته شدن مراجعه کنید.
ماژول ها
ماژول های جاوا اسکریپت به سازماندهی کد جاوا اسکریپت کمک می کنند. اگر به درستی استفاده شوند، ساختار مؤثری برای پایگاه کد شما فراهم می کنند و به استفاده مجدد از کد کمک می کنند. ماژول های جاوا اسکریپت به جای استفاده از متغیرهای سراسری برای اشتراک گذاری متغیرها در فایل های مختلف، تکنیکی برای صادرات و وارد کردن متغیرها ارائه می کنند.
// hello.js file
function hello() {
return 'Hello world!';
}
export { hello };
// app.js file
import { hello } from './hello.js';
console.log(hello()); // Hello world!
نسخه ی نمایشی Scope visualizer
Scope یک مفهوم اساسی است که هر توسعه دهنده جاوا اسکریپت باید آن را درک کند. برای درک بهتر سیستم scope، می توانید سعی کنید کد خود را با JS Scope Visualizer بنویسید. نسخه ی نمایشی از رنگ آمیزی در کد استفاده می کند تا به شما در تجسم محدوده جاوا اسکریپت کمک کند.
نتیجه گیری
این مقاله انواع مختلفی از دامنه را معرفی می کند. دامنه جاوا اسکریپت یکی از مفاهیم پیشرفتهتر در توسعه وب است، بنابراین بسیار خوب است که این محتوا را مطالعه کردهاید و برای درک این موضوع وقت گذاشتهاید.
Scope یک ویژگی برای کاربر نیست. این فقط بر توسعهدهنده وب که کد مینویسد تأثیر میگذارد، اما آگاهی از نحوه عملکرد دامنه میتواند به شما در رفع اشکالها در صورت بروز کمک کند.