في المقدمة السابقة ، نعلم بالفعل أن JavaScript ليس لديها وظيفة على مستوى الكتلة ، فقط نطاق على مستوى الوظيفة.
نسخة الكود كما يلي:
اختبار الوظيفة () {// a scope
لـ (var i = 0 ؛ i <10 ؛ i ++) {// not a scope
// عدد
}
console.log (i) ؛ // 10
}
لا يوجد أيضًا مساحة اسم معروضة في JavaScript ، مما يعني أن كل شيء محدد في النطاق العالمي. في كل مرة يتم فيها الرجوع إلى متغير ، سيجتاز JavaScript النطاق العالمي بأكمله حتى يتم العثور عليه. إذا لم يتم العثور على المتغير من خلال النطاق العالمي الكامل ، يتم إلقاء خطأ مرجعية.
الرجاء إدخال وصف الصورة
المتغيرات العالمية الضمنية
نسخة الكود كما يلي:
// السيناريو أ
foo = '42' ؛
// السيناريو ب
var foo = '42'
مثالان أعلاه لهما تأثيرات مختلفة. الأول سيحدد المتغير FOO في النطاق العالمي ، في حين أن الثانية ستحدد المتغير FOO في النطاق الحالي.
يجب أن نلاحظ أنه إذا لم تستخدم الكلمة الرئيسية VAR ، فسيكون لها تأثير غير متوقع.
نسخة الكود كما يلي:
// النطاق العالمي
var foo = 42 ؛
اختبار الوظيفة () {
// النطاق المحلي
فو = 21 ؛
}
امتحان()؛
فو // 21
نظرًا لأنه لا يتم استخدام VAR لتحديد المتغير FOO في اختبار الوظيفة ، فسيتم كتابة المتغير العالمي FOO خارج الوظيفة. على الرغم من أنها لا تبدو مشكلة كبيرة ، إذا كان هناك آلاف خطوط التعليمات البرمجية ، فسيكون من الصعب تتبعه.
نسخة الكود كما يلي:
// النطاق العالمي
VAR heads = [/ * بعض القائمة */] ؛
لـ (var i = 0 ؛ i <10 ؛ i ++) {
subloop () ؛
}
وظيفة subloop () {
// نطاق subloop
لـ (i = 0 ؛ i <10 ؛ i ++) {// missing var state
// افعل أشياء مذهلة!
}
}
في المثال أعلاه ، ستتوقف الحلقة الخارجية عند تنفيذ التنفيذ الأول ، لأن المتغير I داخل وظيفة Subloop سيتجاوز المتغير العالمي الخارجي i. نحتاج فقط إلى إضافة var داخل الوظيفة لتجنب هذا الخطأ ، لذلك يجب ألا ننسى إضافة الكلمة الرئيسية var عند تحديد المتغيرات. ما لم نرغب في أن يكون لها تأثير على المتغيرات العالمية الخارجية.
المتغيرات المحلية
لا يمكن إنشاء المتغيرات المحلية في JavaScript إلا بطريقتين ، يتم الإعلان عن أحدهما من خلال الكلمة الرئيسية VAR ، والآخر يستخدم كمعلمات رسمية للوظيفة.
نسخة الكود كما يلي:
// النطاق العالمي
var foo = 1 ؛
var bar = 2 ؛
var i = 2 ؛
اختبار الوظيفة (i) {
// النطاق المحلي لاختبار الوظيفة
أنا = 5 ؛
var foo = 3 ؛
شريط = 4 ؛
}
اختبار (10) ؛
في هذا الوقت ، فإن المتغيرات I و FOO داخل اختبار الوظيفة هما المتغيرات المحلية ، وسيقوم BAR بتجاوز شريط المتغير العالمي الخارجي.
الرفع
ستقوم JavaScript بترويج إعلانات متغيرة ، مما يعني أنه سيتم الترويج لكل من تعبيرات VAR وإعلانات الوظائف إلى أعلى النطاق.
نسخة الكود كما يلي:
حاجِز()؛
var bar = function () {} ؛
var somevalue = 42 ؛
امتحان()؛
اختبار الوظيفة (البيانات) {
إذا (خطأ) {
goo = 1 ؛
} آخر {
var goo = 2 ؛
}
لـ (var i = 0 ؛ i <100 ؛ i ++) {
var e = data [i] ؛
}
}
قبل تشغيل الكود أعلاه ، سيتم ترقية إعلان تعبير VAR واختبار الوظيفة إلى الأعلى ، وبالتالي سيتم تشغيل البرنامج بشكل طبيعي ولن يبلغ عن خطأ.
نسخة الكود كما يلي:
// تم نقل عبارات var هنا
var Bar ، SomeValue ؛ // الافتراضي إلى "غير محدد"
// تم نقل إعلان الوظيفة أيضًا
اختبار الوظيفة (البيانات) {
var goo ، i ، e ؛ // مفقود نطاق الكتلة يحرك هذه هنا
إذا (خطأ) {
goo = 1 ؛
} آخر {
goo = 2 ؛
}
لـ (i = 0 ؛ i <100 ؛ i ++) {
e = البيانات [i] ؛
}
}
حاجِز()؛ // يفشل مع typeerror لأن شريط لا يزال "غير محدد"
SomeValue = 42 ؛ // لا تتأثر المهام بالرفع
bar = function () {} ؛
امتحان()؛
نظرًا لأن JavaScript لا يحتوي على نطاق على مستوى الكتلة ، فإن هذا لن يحسن تعبير VAR فقط ، ولكن أيضًا يجعل الهيكل أقل بديهية.
في المثال أعلاه ، على الرغم من أنه يبدو أنه إذا كان يعمل على Gollable Goo ، في الواقع ، نظرًا لترويج GOO المتغير ، يتم تعديل المتغير المحلي.
إذا لم يكن لديك أي فهم لقواعد الارتفاع ، فقد تعتقد أن الكود التالي سوف يرمي خطأ مرجعية.
نسخة الكود كما يلي:
// تحقق مما إذا كان قد تمت تهيئة بعض الشيء
if (! someimimanting) {
var someimimortantthing = {} ؛
}
بطبيعة الحال ، فإن الكود أعلاه ليس خطأ ، لأنه تم ترقية تعبير VAR إلى الأعلى قبل تشغيل الكود.
نسخة الكود كما يلي:
var someimimthanting ؛
// قد تهيئة رمز آخر من كل شيء هنا ، أو لا
// تأكد من وجودها هناك
if (! someimimanting) {
someimimortantthing = {} ؛
}
هنا أود أن أوصي بـ @Nightire Fan GE Post "فهم JavaScript (II)" ، وهو ما يفسر التحسن تمامًا.
أمر قرار الاسم
عند محاولة الوصول إلى متغير FOO ضمن نطاق الوظيفة ، ستبحث JavaScript ذلك بالترتيب التالي:
ما إذا كان هناك تعريف لفار فو في النطاق الحالي.
ما إذا كان هناك متغير FOO في معلمة الوظيفة.
ما إذا كانت الوظيفة نفسها فو.
القفز إلى مجال التعريف الخارجي وابدأ في البحث عن الجزء الأول.
مساحة الاسم
واحدة من أكثر المشاكل شيوعًا هي تسمية النزاعات ، لأن JavaScript لديها نطاق عالمي واحد فقط. ولكن يمكن حل هذه المشكلة عن طريق وظائف خارجية مجهولة.
نسخة الكود كما يلي:
(وظيفة() {
// "مساحة الاسم" التي تحتوي على الذات
window.foo = function () {
// إغلاق مكشوف
} ؛
}) () ؛ // تنفيذ الوظيفة على الفور
تعتبر الوظائف المجهولة في المثال أعلاه تعبيرات ، لذلك يتم تنفيذها.
نسخة الكود كما يلي:
(// تقييم الوظيفة داخل الآباء
وظيفة() {}
) // وإرجاع كائن الوظيفة
() // استدعاء نتيجة التقييم
بالطبع ، يمكننا أيضًا استخدام طرق أخرى لاستدعاء تعبيرات الوظائف ، وهياكل مختلفة ، ولكن نفس التأثير.
نسخة الكود كما يلي:
// بعض الأنماط الأخرى لاستدعاء مباشرة
!وظيفة(){}()
+function () {} ()
(وظيفة(){}())؛
// وهكذا ...
لخص
يوصى باستخدام وظائف خارجية مجهولة المصدر لتغليف الكود في المساحة ، والتي لا تحل فقط تعارضات مساحة الاسم ، ولكنها تسهل أيضًا تعديل البرنامج.
بالإضافة إلى ذلك ، فإن استخدام المتغيرات العالمية ليس عادة جيدة ، والتي ستجلب تكاليف الصيانة المرتفعة وعرضة للأخطاء.
تحتوي مساحات الأسماء على نفس الأنواع والوظائف والمتغيرات والقوالب وما إلى ذلك ، وكلها تنتمي إلى الكيانات.
القواسم المشتركة الرئيسية للكيان هي أنه يمكن أن يكون لها اسم. (بالإضافة إلى ذلك ، يمكن أن تحتوي العلامة أيضًا على اسم ، لكنها ليست كيانًا.)
نطاق مساحة الاسم هو مصطلح عام في النطاق ، وهو موازٍ لنطاق الكتلة ، ونطاق الفئة ، ونطاق النموذج الأولي للوظيفة ، ونطاق الوظيفة (صالح فقط للعلامات). الأسماء المعلنة داخل مساحة الاسم في نطاق مساحة الاسم. تعتبر الأسماء العالمية في نطاق مساحة الاسم العالمي الضمني.
وظيفة مساحة الاسم هي بالفعل نطاق ، لكنها مختلفة عن نطاق بسيط. يمكنك إعلان نفس مساحة الاسم في أماكن متعددة في عدة مرات ، ولكن لا يمكن إعادة تعريف المحتوى الموجود في الداخل. سوف يقومون في النهاية بتوليف مساحة اسم ، تمامًا مثل STD ، تعريفات الماكرو في كل مكان.