اسکوپ (scope) در جاوااسکریپت چیست؟

سلام دوستان. توی این قسمت می‌خوایم یکی دیگه از مفاهیم مهم جاوااسکریپت رو بررسی کنیم. مفهومی که درک کردن صحیح اون باعث میشه با خطاهای کمتری رو به رو بشیم و با خیال راحت‌تر کدنویسی کنیم.

امروز می‌خوایم درباره اسکوپ (Scope) توی جاوااسکریپت صحبت کنیم.

توی این قسمت یاد می‌گیریم که:

  • اسکوپ یا حوزه چیه؟
  • بلاک چیه؟
  • اسکوپ سراسری (Global Scope) چیه؟
  • اسکوپ محلی (Local Scope) چیه؟
  • اسکوپ بلاکی (Block Scope) چیه؟


اسکوپ یا حوزه چیه؟

بطور کلی اسکوپ (Scope) به قسمت‌هایی از برنامه گفته میشه که یک متغیر، تابع، آبجکت و ... قابل دسترسی هست. کد زیر رو اجرا کنید:

const x = 10;

function getX() {
  alert(x);

  const y = 20;
}

getX();
alert(y); // error

توی تابع getX تونستیم به متغیر x که بیرون از تابع تعریف شده دسترسی داشته باشیم و اون رو alert کنیم. همچنین توی این تابع یک متغیر تعریف کردیم به اسم y و اون رو داریم توی خط آخر alert می‌کنیم. اما اینجا خطا می‌گیریم که y تعریف نشده. چرا اینطوری میشه؟ به دلیل قوانینی که اسکوپ‌ها توی جاوااسکریپت دارن! توی این قسمت می‌ریم که این قوانین رو بررسی کنیم.

توی جاوااسکریپت ۳ نوع اسکوپ داریم:

  1. اسکوپ سراسری (Global Scope)
  2. اسکوپ محلی (Local Scope)
  3. اسکوپ بلاکی (Block Scope)

قبل از شروع یک چیز رو باید بررسی کنیم: بلاک یا Block


بلاک چیه؟

به فضایی از کد که بین دو براکت { ... } قرار می‌گیره می‌گیم بلاک. مثلاً فضای داخل if ،while و ... :

if (...) {
  /* 
    Block
  */
}

for (...) {
  /* 
    Block
  */
}

{
  /* 
    Block
  */
}

حالا بریم انواع اسکوپ‌ها رو بررسی کنیم.


اسکوپ سراسری (Global Scope)

به بیرونی‌ترین قسمت یک برنامه جاوااسکریپتی می‌گیم اسکوپ سراسری. متغیرهایی که توی این اسکوپ تعریف میشن، همه جای برنامه قابل دسترسی هستن. مثال زیر رو ببینید:

// Global Scope
const name = &quotDiego&quot

function func() {
  alert(name); // Diego
}

func();

توی این مثال متغیر name توی اسکوپ سراسری تعریف شده. چون محدود شده درون هیچ تابع و بلاکی نیست و در بیرونی‌ترین حالت قرار داره. متغیرهایی که توی اسکوپ سراسری تعریف میشن، توی توابع هم قابل دسترسی هستن. پس کد بالا بدون مشکل اجرا میشه.

متغیرهای سراسری در سراسر برنامه قابل دسترسی هستن.


اسکوپ محلی (Local Scope)

متغیرهایی که توی یک تابع تعریف میشن، اسکوپ لوکال (محلی) دارن و فقط درون خود تابع قابل دسترسی هستن:

// Global Scope

function getUser() {
  // Local Scope

  const user = &quotMario&quot
  alert(user);
}

getUser();   // Mario
alert(user); // ReferenceError: user is not defined

با اجرا شدن کد بالا alert توی خط ۷ به درستی کار میکنه. چون متغیر user توی همون اسکوپ هست. اما alert خط آخر خطا میده چون متغیر user توی این اسکوپ وجود نداره. به اسکوپ لوکال به اصطلاح Function Scope هم گفته میشه.


توابع تو در تو چطور؟

مثال زیر رو در نظر بگیرید:

// Global Scope

function func1() {
  // Local Scope #1
  const name = &quotMario&quot

  function func2() {
    // Local Scope #2 
    const lastname = &quotDoe&quot

    alert(`${name} ${lastname}`);
  }

  func2();
}

func1(); // John Doe

همونطور که می‌بینیم یک تابع به اسم func2 داخل یک تابع دیگه به اسم func1 تعریف شده. طبق قوانین اسکوپ‌ها، توابع داخلی می‌تونن به متغیرهای اسکوپ بیرونی خودشون دسترسی داشته باشن. پس تابع func2 به متغیر name که بیرون از این تابع تعریف شده دسترسی داره. اما عکس این قضیه صادق نیست. اسکوپ‌های بیرونی نمی‌تونن به اعضای اسکوپ‌های داخلی دسترسی داشته باشن:

unction func1() {
  function func2() {
    const x = 10;
  }

  alert(x);
}

func1(); // ReferenceError: x is not defined


اسکوپ بلاکی (Block Scope)

همونطور که گفتیم به فضای بین دو براکت می‌گیم بلاک. متغیرهایی که با let و const توی یک بلاک تعریف میشن فقط توی همون بلاک قابل دسترسی هستن:

{
  let x = 29;
}

alert(x) // ReferenceError: x is not defined

اما برای var اینطوری نیست. متغیری که با var توی یک بلاک تعریف بشه، بیرون بلاک هم قابل دسترسی هست:

{
  var x = 12;
}

alert(x) // 12

در واقع اسکوپی که یک بلاک درست می‌کنه همون اسکوپ محلی هست. یعنی فقط همون‌جا قابل دسترسی هست:

const x = 10;
{
  const x = 20;
  alert(x); // 20
}

alert(x); // 10

با اجرای کد بالا می‌بینیم که متغیر x داخل بلاک هیچ تداخلی با x که بیرون تعریف شده نداره. این دو در واقع دو متغیر جدا هستن.

اگه بلاک‌های تو در تو داشته باشیم، اعضای یک بلاک بیرونی نمی‌تونه به اعضای بلاک‌های داخلی دسترسی داشته باشه؛ اما اعضای داخلی می‌تونن به اعضای بیرونی دسترسی داشته باشن:

const x = 1;
{
  const y = 2;
  {
    alert(x); // ok
    alert(y); // ok

    const z = 3;
  }
  alert(z); // error
}

alert(y); // error

خب دوستان این قسمت هم به پایان رسید. باید بدونیم که با یادگیری مهمترین مفاهیم هر زبان هست که می‌تونیم یک برنامه‌نویس و توسعه‌دهندهٔ با ارزش بشیم.


منابع :