freeCodeCamp/guide/arabic/javascript/scopes/index.md

131 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Scopes
localeTitle: نطاقات
---
إذا كنت تقوم بالبرمجة في JavaScript لفترة من الوقت ، فستواجه بدون شك مفهومًا يعرف باسم `scope` . ما هو `scope` ؟ لماذا يجب أن تأخذ الوقت الكافي لتعلمها؟
في intermer speak ، `scope` هو **سياق التنفيذ الحالي** . مشوش؟ لنلق نظرة على جزء الشفرة التالي:
`var foo = 'Hi, I am foo!';
var baz = function () {
var bar = 'Hi, I am bar too!';
console.log(foo);
}
baz(); // Hi, I am foo!
console.log(bar); // ReferenceError...
`
هذا مثال بسيط ، لكنه يقوم بعمل جيد لتوضيح ما يعرف باسم _نطاق Lexical_ . جافا سكريبت ، وتقريبا كل لغة برمجة أخرى لديها _نطاق Lexical_ . هناك نوع آخر من النطاق يعرف بالنطاق _الديناميكي_ ، لكننا لن نناقش ذلك.
الآن ، يبدو مصطلح _نطاق Lexical_ يتوهم ، ولكن كما سترى ، فإن الأمر بسيط للغاية من حيث المبدأ. في نطاق المعجم ، هناك نوعان من النطاقات: _النطاق العالمي والنطاق_ _المحلي_ .
قبل كتابة السطر الأول من التعليمة البرمجية في البرنامج ، يتم إنشاء _نطاق عالمي من_ أجلك. يحتوي هذا على كافة المتغيرات التي تقوم بتعريفها في البرنامج **خارج أي وظائف** .
في المثال أعلاه ، يكون `foo` المتغير في النطاق العالمي للبرنامج ، بينما يتم الإعلان عن `bar` المتغير داخل دالة وبالتالي يكون **في النطاق المحلي لتلك الوظيفة** .
يتيح تقسيم المثال عن طريق سطر. في حين قد تكون مرتبكًا في هذه المرحلة ، فأعدك أن يكون لديك فهم أفضل بكثير عند الانتهاء من قراءة هذا.
على خط 1 نحن نعلن متغير `foo` . لا شيء يتوهم جدا هنا. دعنا نطلق على هذا إشارة إلى حجم اليسار (LHS) إلى `foo` ، لأننا نقوم بتعيين قيمة `foo` وهي تقع على الجانب الأيسر من علامة `equal` .
في السطر 3 ، نعلن عن وظيفة ونقوم بتعيينها إلى `baz` متغير. هذه إشارة LHS أخرى إلى `baz` . نحن نقوم بتعيين قيمة لها (تذكر ، الدوال هي قيم أيضًا!). ثم يتم استدعاء هذه الدالة على السطر 8. هذا هو RHS ، أو إشارة الجانب الأيمن إلى `baz` . نحن `baz` قيمة `baz` ، والتي في هذه الحالة دالة ثم تستدعيها. سيكون مرجع RHS آخر إلى `baz` إذا قمنا بتعيين قيمته إلى متغير آخر ، على سبيل المثال `foo = baz` . سيكون هذا إشارة LHS إلى `foo` وإشارة RHS إلى `baz` .
قد تبدو المراجع LHS و RHS مربكة ، ولكنها مهمة لمناقشة النطاق. فكر في الأمر بهذه الطريقة: يقوم مرجع LHS بتعيين قيمة للمتغير ، بينما يقوم مرجع RHS باسترداد قيمة المتغير. إنها طريقة أقصر وأكثر ملاءمةً للقول "استرداد القيمة" و "تعيين قيمة".
دعونا الآن نقوم بتعطل ما يحدث داخل الوظيفة نفسها.
عندما يجمع المحول البرمجي الرمز داخل دالة ، فإنه يدخل **النطاق المحلي** للوظيفة.
على الخط 4 ، يتم التصريح عن `bar` المتغير. هذه إشارة LHS إلى `bar` . في السطر التالي ، لدينا مرجع RHS `foo` داخل `console.log()` . تذكر أننا `foo` قيمة `foo` ثم نمررها كحجة إلى `console.log()` .
عندما يكون لدينا مرجع RHS إلى `foo` ، يبحث المترجم عن إعلان المتغير `foo` . لا يجدها المحول البرمجي في الوظيفة نفسها ، أو **النطاق المحلي للوظيفة ،** حيث **يرتفع مستوى واحد: إلى النطاق العالمي** .
في هذه المرحلة ، ربما تفكر في أن النطاق له علاقة بالمتغيرات. هذا صحيح. يمكن اعتبار النطاق بمثابة حاوية للمتغيرات. لا يمكن الوصول إلى جميع المتغيرات التي يتم إنشاؤها داخل نطاق محلي إلا في النطاق المحلي. ومع ذلك ، يمكن لكافة النطاقات المحلية الوصول إلى النطاق العالمي. (أعلم أنك على الأرجح أكثر إرباكًا الآن ، لكن فقط تحمل معي لفقرات قليلة أخرى).
وبالتالي فإن المترجم ترتفع إلى نطاق عالمي لإيجاد مرجعية LHS إلى متغير `foo` . يجد واحدًا على السطر 1 ، بحيث يسترد القيمة من مرجع LHS ، وهو سلسلة: `'Hi, I am foo!'` . يتم إرسال هذه السلسلة إلى الأسلوب `console.log()` و outputted إلى وحدة التحكم.
انتهى المحول البرمجي من تنفيذ الشفرة داخل الدالة ، لذا نعود إلى السطر 9. في السطر 9 ، لدينا مرجع RHS `bar` المتغير.
الآن ، أعلن `bar` في النطاق المحلي من `baz` ، ولكن هناك إشارة RHS `bar` في النطاق العالمي. نظرًا لعدم وجود مرجع LHS `bar` في النطاق العالمي ، فلن يتمكن المحول البرمجي من العثور على قيمة `bar` ويلقي ReferenceError.
ولكن ، قد تسأل ، إذا كانت الوظيفة يمكن أن تبدو خارج نفسها للمتغيرات ، أو نطاق محلي يمكن أن ينظر إلى النطاق العالمي للعثور على مراجع LHS ، فلماذا لا يستطيع النطاق العالمي النظر إلى نطاق محلي؟ حسنا هذا هو كيف يعمل المدى معجمي!
`... // global scope
var baz = function() {
... // baz's scope
}
... /// global scope
`
هذا هو نفس رمز من أعلاه الذي يوضح النطاق. يشكل هذا نوعًا من التسلسل الهرمي الذي يرتقي إلى النطاق العالمي:
`baz -> global` .
لذا ، إذا كان هناك مرجع RHS لمتغير داخل نطاق `baz` ، فيمكن تحقيقه بواسطة مرجع LHS لهذا المتغير في النطاق العالمي. لكن العكس **ليس صحيحًا** .
ماذا لو كان لدينا وظيفة أخرى داخل `baz` ؟
`... // global scope
var baz = function() {
... // baz's scope
var bar = function() {
... // bar's scope.
}
}
... /// global scope
`
في هذه الحالة ، سيبدو التسلسل الهرمي أو **سلسلة النطاق** كما يلي:
`bar -> baz -> global`
أي إشارات RHS داخل `bar` 'نطاق محلي الصورة يمكن fullfilled بالإشارة LHS في نطاق عالمي أو `baz` "نطاق الصورة، ولكن إشارة RHS في `baz` " نطاق الصورة لا يمكن fullfilled بالإشارة LHS في `bar` "نطاق الصورة.
**يمكنك فقط عبور سلسلة نطاق ، وليس لأعلى.**
هناك شيئين مهمين آخرين يجب معرفتهما حول نطاقات جافا سكريبت.
1. يتم الإعلان عن النطاقات بواسطة الدالات ، وليس بواسطة الكتل.
2. وظائف يمكن الرجوع إلى الأمام ، المتغيرات لا يمكن.
لاحظ (كل تعليق يصف النطاق الموجود في السطر المكتوب عليه):
\`\` \` // outer () في النطاق هنا لأن الدالات يمكن أن تكون مرجعية للأمام
`function outer() {
// only inner() is in scope here
// because only functions are forward-referenced
var a = 1;
//now 'a' and inner() are in scope
function inner() {
var b = 2
if (a == 1) {
var c = 3;
}
// 'c' is still in scope because JavaScript doesn't care
// about the end of the 'if' block, only function inner()
}
// now b and c are out of scope
// a and inner() are still in scope
}
// here, only outer() is in scope
`
\`\` \`
# المراجع
1. [نطاقات وإغلاق](https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures) بواسطة كايل سيمبسون. يذهب إلى مزيد من التفاصيل حول كيفية عمل آلية النطاق ، ولديه أيضًا وصفًا سطحيًا لكيفية عمل مترجم جافا سكريبت ، لذلك إذا كنت مهتمًا بذلك ، فقم بالتأكيد بإعطائه قراءة! إنه مجاني على GitHub ويمكن شراؤه من O'Reilly.
2. [أسرار جافا سكريبت النينجا من](https://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/1617292850/ref=pd_lpo_sbs_14_img_0?_encoding=UTF8&psc=1&refRID=YMC2TB2C0DFHTQ3V62CA) قبل جون Resig والدب Bibeault. دليل رائع لفهم أكثر عمقًا لجافا سكريبت.