في كل لغة برمجة ، فإن متغيراتها لها نطاق صالح معين. بعد تجاوز هذا النطاق ، ستصبح المتغيرات غير صالحة. هذا هو نطاق المتغير. من وجهة نظر رياضية ، هو مجال المتغيرات المستقلة.
النطاق هو النطاق الذي يمكن الوصول إليه من المتغيرات ، أي النطاق يتحكم في رؤية وحيرة الحياة للمتغيرات والوظائف. في JavaScript ، تكون الكائنات والوظائف هي أيضًا متغيرات ، ويتم تعريف المتغيرات داخل جسم الوظيفة التعسفية المتداخلة عن طريق إعلان جسم وظيفتها وجسم الوظيفة التعسفية المتداخلة.
1. النطاق الثابت والنطاق الديناميكي
نطاق ثابت
وهذا يعني أن نطاق الإعلان يتم تحديده في وقت الترجمة بناءً على هيئة البرنامج ، والمعروفة أيضًا باسم النطاق المعجمي. تتبنى معظم لغات البرمجة الحديثة قواعد نطاق ثابتة ، وتبني JavaScript هذا النطاق.
في اللغات التي تستخدم نطاقات ثابتة ، تكون قواعد النطاق المتداخلة الأعمق في الأساس: المعرف الذي أدخله إعلان مرئي في النطاق الذي يوجد فيه الإعلان ، وأيضًا في كل نطاق متداخل ، ما لم يتم تغطيته بإعلان آخر من المعرف الاسم نفسه المتداخل.
من أجل العثور على الكائن المشار إليه بواسطة معرف معين ، يجب العثور عليه في نطاق الأعمق الحالي. إذا تم العثور على إعلان ، يمكن العثور على الكائن المشار إليه بواسطة المعرف. خلاف ذلك ، سوف نبحث في النطاق الخارجي المباشر ونواصل التحقق من النطاق الخارجي من أجل الخارج حتى نصل إلى مستوى التعشيش الخارجي للبرنامج ، أي النطاق الذي يوجد فيه إعلان الكائن العالمي. إذا لم يتم العثور على إعلان على جميع المستويات ، فإن البرنامج لديه خطأ. على النحو التالي:
دالة cha () {var name = "xiao ؛" دالة chb () {function chc () {console.log (name) ؛ }}}أولاً ، تبحث الوظيفة عن تعريف الاسم من chb () ، ثم تستمر في البحث عن الطبقة حسب الطبقة. أخيرًا ، تم العثور على تعريف الاسم في Cha (). إذا لم يتم العثور عليها ، فسيتم الإبلاغ عن خطأ.
2. النطاق الديناميكي
في لغة نتوء ديناميكيًا ، يتم تحديد الكائن المشار إليه بواسطة متغير في البرنامج بناءً على معلومات تدفق التحكم في البرنامج في لحظة تشغيل البرنامج.
2. نطاق جافا سكريبت
يوجد نطاقات في JavaScript ، وهما النطاق العالمي والنطاق المحلي.
1. النطاق العالمي
هناك تعريف في أي مكان في الكود. حتى إذا تم تعريف متغير عالمي في جزء من رمز JS المتداخل في صفحة HTML ، فلا يزال من الممكن الوصول إلى المتغير في ملف JS المشار إليه. من المحتمل جدًا أن يتسبب هذا في التلوث للمتغيرات العالمية.
سيتم اعتبار المتغيرات في الحالات الثلاث التالية متغيرات عالمية
(1) الوظيفة الخارجية والمتغير الخارجي لها نطاق عالمي
(2) يتم الإعلان تلقائيًا من المتغيرات التي يتم تعيينها مباشرة بدون تعريف
(3) خصائص جميع كائنات النوافذ لها نطاق عالمي
2. النطاق المحلي
لا يمكن الوصول إلى النطاقات المحلية بشكل عام إلا في مقتطفات الرمز الثابت ، مثل المتغيرات داخل الوظائف (نطاق الوظيفة)
var name = "xuxiooping" ؛ function echoname () {var firstName = "Xu" ؛ // local scope SecondName = "Xiao" ؛ // Global Scope function echofirstname () {console.log (الاسم الأول) ؛ // xu} console.log (SecondName) ؛ إرجاع echofirstname ؛} console.log (name) ؛ // Global Scope var f = echoname () ؛ f () ؛ console.log (firstName) ؛ console.log (secondName) ؛النتيجة هي:
xuxiooping
شياو
يمكن للوظيفة الداخلية Xu // الوصول إلى متغيرات الوظيفة الخارجية
لا يمكن الوصول إلى المتغيرات الداخلية للوظيفة الداخلية خارج الوظيفة.
شياو
يرفق JavaScript المتغيرات العالمية على كائنات النوافذ ويصبح خاصية لكائنات النوافذ.
3. نطاق الوظيفة
نطاق مستوى الكتلة: تنتمي أي مجموعة من العبارات في الأقواس إلى كتلة ، وجميع المتغيرات المحددة في هذا غير مرئية خارج كتلة الكود. معظم لغات الفئة C لها نطاقات على مستوى الكتلة.
ومع ذلك ، فإن ميزة مهمة لجافا سكريبت هي أنه ليس لديه نطاق على مستوى الكتلة.
دالة echoi () {for (var i = 0 ؛ i <10 ؛ i ++) {؛ // console.log (i) ؛ } if (true) {var str = "hello" ؛ } console.log (i) ؛ console.log (str) ؛} echoi () ؛نتيجة الإخراج هي:
10
مرحبًا
يمكن ملاحظة أنه خارج البيان (أو إذا ، أثناء) ، لا يزال المتغير الذي حددته في الكتلة متاحًا. أي أن JavaScript لا يدعم النطاقات على مستوى الكتلة ، فهو يدعم فقط نطاقات الوظائف ، والمتغيرات المحددة في أي مكان في وظيفة ما هي مرئية في أي مكان في هذه الوظيفة. كشخص يتعلم C و Java منذ البداية ، من الصعب بعض الشيء للتكيف. وفقا لاختباراتي ، وينطبق الشيء نفسه على PHP.
بالطبع ، يمكنك استخدام خصائص الإغلاق لـ JavaScript لمحاكاة نطاق مستوى الكتلة
دالة echoi () {(function () {for (var i = 0 ؛ i <10 ؛ i ++) {؛ // console.log (i) ؛}}) () ؛ if (true) {var str = "hello" ؛ } console.log (i) ؛ console.log (str) ؛} echoi () ؛والنتيجة هي: أنا غير محدد
هذا يعزل تعريف المتغيرات. في JS ، من أجل منع تعارضات تسمية ، ينبغي تجنب المتغيرات العالمية والوظائف العالمية قدر الإمكان ، لذلك يتم استخدام هذا النوع من الإغلاق بعدة طرق.
4. دورة حياة جافا سكريبت
تتم تهيئة دورة حياة متغير JavaScript عند إعلانها.
يتم تدمير المتغيرات المحلية بعد تنفيذ الوظيفة.
يتم تدمير المتغيرات العالمية بعد إغلاق الصفحة.
3. سلسلة نطاق JavaScript
يبدو وكأنه سلسلة ، وربما يمكن دمجها مع القائمة المرتبطة في بنية البيانات.
في JavaScript ، الوظائف هي كائنات ، ولكن في الواقع ، كل شيء في JavaScript هو كائنات. تحتوي كائنات الوظائف ، مثل الكائنات الأخرى ، على خصائص يمكن الوصول إليها من خلال التعليمات البرمجية وسلسلة من الخصائص الداخلية التي لا يمكن الوصول إليها إلا لمحرك JavaScript. واحدة من الخصائص الداخلية هي [[النطاق]] ، المحددة في الطبعة الثالثة من معيار ECMA-262. تحتوي هذه الخصائص الداخلية على مجموعة من الكائنات في النطاق الذي تم إنشاؤه بواسطة الوظيفة. تسمى هذه المجموعة سلسلة نطاق الوظائف ، والتي تحدد البيانات التي يمكن الوصول إليها بواسطة الوظائف.
عند إنشاء وظيفة ، يتم ملء سلسلة نطاقها باستخدام كائنات بيانات يمكن الوصول إليها في نطاق الوظيفة. على سبيل المثال ، حدد وظيفة مثل هذه:
وظيفة إضافة (num1 ، num2) {var sum = num1 + num2 ؛ إرجاع مجموع ؛}عند إنشاء إضافة الوظيفة ، سيتم ملء كائن عالمي في سلسلة نطاقه ، والتي تحتوي على جميع المتغيرات العالمية ، كما هو موضح في الشكل أدناه (ملاحظة: تعطي الصورة فقط بعض المتغيرات):
سيتم استخدام نطاق الوظيفة إضافة أثناء التنفيذ. على سبيل المثال ، قم بتنفيذ الكود التالي:
var total = add (5،10) ؛
عند تنفيذ هذه الوظيفة ، يتم إنشاء كائن داخلي يسمى "سياق التنفيذ". يحدد سياق وقت التشغيل البيئة التي يتم تنفيذ الوظيفة. كل سياق وقت التشغيل له سلسلة نطاقها الخاصة لتحليل المعرف. عند إنشاء سياق وقت التشغيل ، تتم تهيئة سلسلة نطاقه ككائن موجود في [[النطاق]] لوظيفة التشغيل الحالية.
يتم نسخ هذه القيم في سلسلة نطاق سياق وقت التشغيل بالترتيب الذي تظهر به في الوظيفة. تشكل معًا كائنًا جديدًا يسمى "كائن التنشيط" ، والذي يحتوي على جميع المتغيرات المحلية ، والمعلمات المسمى ، ومجموعات المعلمات وهذه الوظيفة. ثم سيتم دفع هذا الكائن إلى الطرف الأمامي لسلسلة النطاق. عندما يتم تدمير سياق الجري ، سيتم تدمير الكائن النشط. يظهر سلسلة النطاق الجديدة في الشكل أدناه:
أثناء تنفيذ الوظيفة ، في كل مرة يتم فيها مواجهة متغير ، سيتم تمرير عملية تحليل المعرف لتحديد مكان الحصول على البيانات وتخزينها. تبدأ هذه العملية من رأس سلسلة النطاق ، أي يبحث عن معرف يحمل نفس الاسم من الكائن النشط. إذا تم العثور عليه ، استخدم المتغير المقابل لهذا المعرف. إذا لم يتم العثور عليها ، فاستمر في البحث عن الكائن التالي في سلسلة النطاق. إذا لم يتم العثور على جميع الكائنات بعد البحث ، فإن المعرف يعتبر غير محدد. أثناء تنفيذ الوظيفة ، يجب أن يمر كل معرف من خلال عملية البحث هذه.
4. سلسلة النطاق وتحسين الكود
من بنية سلسلة النطاق ، يمكن ملاحظة أنه في سلسلة النطاق في سياق وقت التشغيل ، كلما كان المعرف الأعمق هو أبطأ سرعة القراءة والكتابة. كما هو موضح في الشكل أعلاه ، نظرًا لوجود المتغيرات العالمية دائمًا في نهاية سلسلة نطاق السياق أثناء وقت التشغيل ، فمن الأبطأ إيجاد متغيرات عالمية عند تحليل المعرف. لذلك ، عند كتابة التعليمات البرمجية ، يجب أن تحاول استخدام المتغيرات العالمية بأقل قدر ممكن واستخدام المتغيرات المحلية قدر الإمكان. هناك قاعدة جيدة من الإبهام هي: إذا تمت الرجوع إلى كائن متقاطع أكثر من مرة ، فقم بتخزينه في متغير محلي قبل الاستخدام. على سبيل المثال ، الكود التالي:
وظيفة changeColor () {document.getElementById ("btnchange"). onClick = function () {document.getElementById ("TargetCanvas"). style.backgroundColor = "Red" ؛ } ؛}تشير هذه الوظيفة إلى المستند العالمي المتغير مرتين. يجب البحث عن المتغير من خلال سلسلة النطاق بأكملها حتى يتم العثور عليها أخيرًا في الكائن العالمي. يمكن إعادة كتابة هذا الرمز على النحو التالي:
وظيفة changeColor () {var doc = document ؛ doc.getElementById ("btnchange"). onClick = function () {doc.getElementById ("targetCanvas"). style.backgroundColor = "Red" ؛ } ؛}هذا الرمز بسيط نسبيًا ولن يظهر تحسينًا كبيرًا للأداء بعد إعادة الكتابة ، ولكن إذا تم الوصول إلى عدد كبير من المتغيرات العالمية في البرنامج بشكل متكرر ، فسيتم تحسين أداء الكود بعد إعادة الكتابة بشكل كبير.
5. مع سلسلة نطاق التغيير
سياق وقت التشغيل المقابل فريد من نوعه في كل مرة يتم تنفيذ الرقم ، لذا فإن استدعاء الوظيفة نفسها عدة مرات سيؤدي إلى إنشاء سياقات وقت تشغيل متعددة. عند تنفيذ الوظيفة ، سيتم تدمير سياق التنفيذ. يرتبط كل سياق وقت التشغيل بسلسلة النطاق. بشكل عام ، خلال سياق الجري ، ستتأثر سلسلة نطاقها فقط بالبيان مع بيان الصيد.
يعد البيان طريقة سريعة لتطبيق الكائنات لتجنب كتابة التعليمات البرمجية المكررة. على سبيل المثال:
وظيفة initUi () {مع (المستند) {var bd = body ، links = getElementSbyTagName ("a") ، i = 0 ، len = links.length ؛ بينما (i <len) {update (links [i ++]) ؛ } getElementById ("btninit"). onClick = function () {dosomething () ؛ } ؛ }}استخدم عبارات العرض هنا لتجنب كتابة المستند عدة مرات ، والتي تبدو أكثر كفاءة ، ولكنها تخلق في الواقع مشاكل في الأداء.
عندما يتم تشغيل الرمز إلى البيان مع ، يتم تغيير سلسلة نطاق سياق وقت التشغيل مؤقتًا. يتم إنشاء كائن جديد قابل للتغيير ، والذي يحتوي على جميع خصائص الكائن المحدد بواسطة المعلمة. سيتم دفع هذا الكائن إلى رأس سلسلة النطاق ، مما يعني أن جميع المتغيرات المحلية للوظيفة موجودة الآن في كائن سلسلة النطاق الثاني ، لذلك يكون الوصول أكثر تكلفة. كما هو مبين في الشكل أدناه:
لذلك ، يجب تجنب البيانات في البرامج. في هذا المثال ، ببساطة تخزين المستند في متغير محلي يمكن أن يحسن الأداء.
لخص
1. نطاق المتغير هو حيث يكون نطاق المتغير صالحًا.
2. سلسلة نطاق المتغيرات هي مجموعة الكائنات في النطاق الذي تم إنشاؤه.
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون من المفيد للجميع تعلم برمجة JavaScript.