نطاق المتغيّر العام والمحلي

في هذه المقالة، ستتعرّف على النطاق وآلية عمله في JavaScript.

النطاق هو مفهوم أساسي في JavaScript ولغات البرمجة الأخرى، وهو يحدد السياق الذي يتم فيه الوصول إلى المتغيرات واستخدامها. وتصبح أكثر فائدة وقابلية للتطبيق على التعليمات البرمجية الخاصة بك مع استمرارك في تعلم JavaScript والعمل بشكل أكبر باستخدام المتغيرات.

يمكن أن يساعدك النطاق في تحقيق ما يلي:

  • استخدام الذاكرة بكفاءة أكبر: يتيح النطاق إمكانية تحميل المتغيّرات عند الحاجة فقط. إذا كان المتغير خارج النطاق، فلا تحتاج إلى إتاحته للرمز قيد التنفيذ حاليًا.
  • العثور على الأخطاء وإصلاحها بسهولة أكبر: يُسهِّل فصل المتغيرات باستخدام النطاق المحلي تحديد الأخطاء في الرمز البرمجي وحلّها، لأنّه على عكس المتغيرات العامة، يمكنك الوثوق بهذا الرمز البرمجي من نطاق خارجي لعدم تمكّنه من معالجة المتغيرات ذات النطاق المحلي.
  • إنشاء مجموعات صغيرة من الرموز البرمجية القابلة لإعادة الاستخدام: على سبيل المثال، يمكنك كتابة دالة خالصة لا تعتمد على النطاق الخارجي. يمكنك بسهولة نقل مثل هذه الدالة إلى مكان آخر مع إدخال تغييرات بسيطة.

ما النطاق؟

يحدد نطاق المتغير المكان الذي يمكنك فيه استخدام المتغير داخل التعليمة البرمجية.

تحدد JavaScript متغيرات النطاق العمومي أو المحلي:

  • وتتوفر المتغيرات ذات النطاق العمومي من جميع النطاقات الأخرى ضمن رمز JavaScript.
  • لا تتوفّر المتغيرات ذات النطاق المحلي إلا ضمن سياق محلي معيّن ويتم إنشاؤها باستخدام كلمات رئيسية، مثل var وlet وconst. إذا كنت تستخدم الكلمات الرئيسية var أو let أو const لإنشاء متغيّر ضمن دالة، يكون لهذا المتغيّر نطاقًا محليًا.

تناقش الأقسام اللاحقة في هذه المقالة الحظر والنطاق اللغوي:

  • تتوفّر متغيّرات حظر النطاق محليًا للكتلة على النحو الذي يتم تحديده من خلال موقع الأقواس المعقوفة حيث يتم تحديد عبارة الحظر. فقط المتغيّرات التي تم تعريفها باستخدام الكلمات الرئيسية let أو const هي التي لها نطاق حظر.
  • يستخدم النطاق المعجمي الموقع الجغرافي الذي تم تعريف المتغيّر فيه في رمز المصدر لتحديد مكان توفُّر ذلك المتغيّر. تستخدم حالات الإغلاق لمنح دالة مضمنة إمكانية الوصول إلى المتغيرات المشار إليها في النطاق الخارجي المعروف باسم البيئة المعجمية.

عند الوصول إلى متغير ضمن نطاقه، تُرجع JavaScript قيمته المخصصة أو تنتج خطأ.

لتعريف متغيّر:

  • استخدِم الكلمات الرئيسية var أو const أو let للإعلان عن متغيرات النطاق المحلية أو العامة.
  • استخدِم الكلمات الرئيسية const أو let للإشارة إلى متغيّرات نطاق الحظر.

عندما تُعلن عن متغيّر var في إحدى الدوال، يتيح هذا التعريف إتاحة المتغيّر لأقرب دالة تضمين. لا يمكنك استخدام الكلمة الرئيسية var للإشارة إلى المتغيّرات في نطاق الحظر.

أمثلة على النطاق

يوضّح هذا المثال النطاق العمومي لأنه تم الإعلان عن المتغيّر greeting خارج أي دالة أو كتلة، ما يجعل قيمته متاحة لكل الرموز البرمجية في المستند الحالي:

const greeting = 'hello';
console.log(greeting); // 'hello'

في مثال النطاق العمومي، يتم تعيين قيمة hello للمتغيّر greeting.

يوضّح هذا المثال النطاق المحلي لأنّه يعرّف المتغيّر 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، تعرض لغة JavaScript رسالة خطأ ReferenceError بدلاً من رسالة hello المتوقّعة. لماذا؟

يتم عرض خطأ لأنّ المتغيّر greeting له نطاق حظر وتشكّل أقرب كتلة جزءًا من عبارة if الشرطية. لا يمكنك الوصول إلى متغيّرَي let وconst اللذَين تعلنهما داخل مجموعة من خارج المجموعة. وبالتالي، يمكنك الوصول إلى المتغيّر greeting فقط بين الأقواس المعقوفة التي تحدّد نطاق الحظر.

يُصلح هذا المثال الخطأ لأنّه ينقل الطريقة console.log(message) داخل الأقواس المعقوفة. يغيّر الرمز المعدَّل موضع الطريقة console.log(message) داخل المجموعة.

if (true) {
   const greeting = 'hello';
   console.log(greeting);
}

أنواع النطاق

النطاق العالمي

يمكنك الوصول إلى المتغيرات بنطاق عمومي من أي مكان في البرنامج.

جرِّب استخدام ملف HTML يستورد ملفَّي JavaScript: file-1.js وfile-2.js:

<script src="file-1.js"></script>
<script src="file-2.js"></script>

في هذا المثال، يكون للمتغير globalMessage نطاق عمومي وتتم كتابته خارج دالة. أثناء التشغيل والتنفيذ، يمكنك الوصول إلى قيمة المتغيّر globalMessage من أي مكان في برنامج JavaScript.

يمكنك الاطّلاع على محتوى ملفَّي 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!

هناك نوع آخر من النطاقات لم تتم مناقشته بشدة في هذه المقالة. عند إنشاء متغيّر ضمن وحدة JavaScript ولكن خارج دالة أو كتلة، لن يتوفّر له نطاق عمومي، بل على نطاق وحدة. تتوفر المتغيرات ذات نطاق الوحدة في أي مكان داخل الوحدة الحالية، ولكنها غير متاحة في الملفات أو الوحدات الأخرى. لإتاحة متغيّر على مستوى الوحدة لملفات أخرى، يجب تصدير هذا المتغيّر من الوحدة التي تم إنشاؤها فيه، ثم import من الوحدة التي تحتاج إلى الوصول إلى المتغيّر.

النطاق المحلي ونطاق الدالة

عند إنشاء متغيّرات في دالة JavaScript باستخدام الكلمات الرئيسية var أو let أو const، تكون المتغيرات محلية للدالة، وبالتالي لا يمكنك الوصول إليها إلا من داخل الدالة. يتم إنشاء المتغيرات المحلية عند بدء إحدى الدوال ويتم حذفها بفعالية عند انتهاء تنفيذ الدالة.

يعلن هذا المثال المتغير total في الدالة addNumbers(). يمكنك الوصول فقط إلى المتغيّرات a وb, وtotal في الدالة addNumbers().

function addNumbers(a, b) {
    const total = a + b;
}

addNumbers(3, 4);

يمكنك استخدام الكلمتَين الرئيسيتَين let وconst لتسمية المتغيرات. عند استخدام الكلمة الرئيسية let، يمكن بلغة JavaScript تعديل المتغيّر. ومع ذلك، عند استخدام الكلمة الرئيسية 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 لتعريف متغيّر محلي في النطاق المحظور. تجدر الإشارة إلى أنه لا يمكنك استخدام الكلمة الرئيسية 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.

إعادة استخدام اسم متغيّر في نطاق مختلف

يمكن للنطاق عزل متغير داخل دالة، حتى عند إعادة استخدام اسم المتغير نفسه في مكان آخر في نطاق مختلف.

يوضِّح هذا المثال كيف يتيح لك استخدام النطاق إعادة استخدام اسم المتغيّر نفسه في دوال مختلفة:

function listOne() {
    let listItems = 10;
    console.log(listItems); // 10
}

function listTwo() {
   let listItems = 20;
   console.log(listItems); // 20
}

listOne();
listTwo();

يتم تحديد القيم المتوقّعة لمتغيّرَي listItems في الدالتَين listOne() وlistTwo()، وبالتالي لا تتعارضان مع بعضهما البعض.

عمليات الإغلاق والنطاق اللغوي

تشير عمليات الإغلاق إلى دالة مضمنة يمكن من خلالها لدالة داخلية الوصول إلى نطاق الدالة الخارجية، والتي تُعرف أيضًا باسم البيئة المعجمية. وبالتالي، في JavaScript، يمكنك استخدام الإغلاق للسماح للدوال بالإشارة إلى البيئة المعجمية الخارجية، والتي تتيح التعليمة البرمجية داخل متغيرات مرجع الدالة التي تم تعريفها خارج الدالة. في الواقع، يمكنك ترميز سلسلة من المراجع للبيئات المعجمية الخارجية بحيث يتم استدعاء الدالة بواسطة دالة، والتي بدورها تستدعيها دالة أخرى.

في هذا المثال، يشكّل الرمز إغلاقًا باستخدام البيئة المعجمية التي يتم إنشاؤها عند استدعاء الدالة outer()، والتي يتم إغلاقها فوق المتغيّر hello. وبالتالي، يتم استخدام المتغير hello في دالة رد الاتصال setTimeout.

function outer() {
    const hello = 'world';

    setTimeout(function () {
        console.log('Within the closure!', hello)
    }, 100);
}

outer();

يُحدَّد النطاق أثناء تجميع رمز المصدر وليس في وقت التشغيل باستخدام النطاق المعجمي. لمعرفة المزيد من المعلومات عن البيئة المعجمية، راجع تحديد النطاق المجّاني والإغلاق.

الوحدات

تساعد وحدات JavaScript في تنظيم رمز JavaScript. وعند استخدامها بشكل صحيح، توفر هيكلاً فعالاً لقاعدة التعليمات البرمجية الخاصة بك وتساعد في إعادة استخدام التعليمة البرمجية. بدلاً من استخدام المتغيرات العمومية لمشاركة المتغيرات عبر ملفات مختلفة، توفر وحدات JavaScript أسلوبًا لتصدير وimport المتغيرات.

// hello.js file
function hello() {
  return 'Hello world!';
}

export { hello };

// app.js file
import { hello } from './hello.js';

console.log(hello()); // Hello world!

الإصدار التجريبي من العرض المرئي للنطاق

النطاق هو مفهوم أساسي يجب أن يفهمه كل مطور JavaScript. لفهم نظام النطاق بشكل أفضل، يمكنك محاولة كتابة التعليمات البرمجية الخاصة بك باستخدام عارِض نطاق JavaScript. يستخدم العرض التوضيحي اللون في التعليمة البرمجية لمساعدتك في تصور نطاقات JavaScript.

الخاتمة

تقدم هذه المقالة أنواعًا مختلفة من النطاقات. إنّ نطاق JavaScript هو أحد المفاهيم الأكثر تقدّمًا في مجال تطوير الويب، لذا من الرائع أن تكون قد قرأت هذا المحتوى وخصّصت وقتًا لفهم هذا الموضوع.

النطاق ليس ميزة موجّهة للمستخدم. إنه يؤثر فقط على مطور الويب الذي يكتب التعليمات البرمجية، ولكن المعرفة بكيفية عمل النطاق يمكن أن تساعدك في إصلاح الأخطاء عند ظهورها.