كيف تبدأ سريعًا مع VUE3.0: أدخل التعلم
التوصيات ذات الصلة: دروس JavaScript التعليمية
غالبًا ما نسمع "بيئة التنفيذ"، "النطاق"، "النموذج الأولي (السلسلة)"، "سياق التنفيذ"، وما إلى ذلك. ماذا تصف؟
نحن نعلم أن js هي لغة مكتوبة بشكل ضعيف، ويتم تحديد نوع المتغير فقط في وقت التشغيل. عندما ينفذ محرك JS كود JS، فإنه سيقوم أيضًا بإجراء التحليل المعجمي ، وتحليل بناء الجملة ، والتحليل الدلالي والمعالجة الأخرى من أعلى إلى أسفل، وإنشاء AST (شجرة بناء جملة مجردة) بعد اكتمال تحليل الكود، وأخيرًا إنشاء كود الآلة التي يمكن لوحدة المعالجة المركزية تنفيذها بناءً على AST وتنفيذها.
بالإضافة إلى ذلك، سيقوم محرك JS أيضًا بإجراء عمليات معالجة أخرى عند تنفيذ التعليمات البرمجية، على سبيل المثال، هناك مرحلتان في V8:
وهذا يؤدي إلى مفهومين: "سياق التنفيذ" و"سلسلة النطاق".
يمكننا أن نعرف مما سبق: عندما ينفذ كود js جزءًا من التعليمات البرمجية القابلة للتنفيذ، سيتم إنشاء سياق التنفيذ المقابل.
بادئ ذي بدء، هناك مفهوم يتوافق مع التعليمات البرمجية القابلة للتنفيذ في JS: "بيئة التنفيذ" - البيئة العالمية، بيئة الوظيفة eval
.
ثانيًا، هناك ثلاث سمات مهمة لكل سياق تنفيذ:
دعنا نلقي نظرة على جزأين من التعليمات البرمجية:
varscope="globalscope"{; فار نطاق = "النطاق المحلي"؛ وظيفة و () { نطاق العودة؛ } return f();}checkscope()
; فار نطاق = "النطاق المحلي"؛ وظيفة و () { نطاق العودة؛ } return f;}checkscope();
ماذا سيطبعون؟
لماذا؟ الجواب هو أن مكدسات سياق التنفيذ الخاصة بها مختلفة!
يمكننا استخدام المصفوفة بالكامل لمحاكاة سلوكها (يوجدما هو "مكدس سياق التنفيذ"؟
عند تنفيذ تعليمات برمجية قابلة للتنفيذ، سيتم إجراء الاستعدادات مسبقًا. تسمى "التحضيرات" هنا بشكل احترافي "سياق التنفيذ". ولكن مع زيادة التعليمات البرمجية القابلة للتنفيذ مثل الوظائف، كيف يمكن إدارة العديد من سياقات التنفيذ؟ لذلك أنشأ محرك JS مفهوم مكدس سياق التنفيذ.
دائمًا
سياق تنفيذ عالمي globalContext في أسفل المكدس).
نحدد EStack، أولاً
EStack=[globalContext]
؛
Push(<checkscope> functionContext); EStack.push(<f> functionContext);EStack.pop();EStack.pop();
والجزء الثاني من التعليمات البرمجية يشبه هذا:
EStack.push(<checkscope> functionContext); EStack.pop();EStack.push (<f> functionContext);EStack.pop();
والسبب هو أنك قد تحتاج إلى دراسة مفهوم "الإغلاق" أولاً!
بالمناسبة، كيف يمكن تحقيق "توفير البيانات على المدى الطويل" في "وحدة الواجهة الأمامية"؟
مخبأ؟ لا. إنهاء!
أولاً وقبل كل شيء، يشير النطاق إلى المنطقة في البرنامج حيث يتم تعريف المتغيرات. يحدد النطاق كيفية العثور على المتغير، والذي يحدد حقوق الوصول للتعليمات البرمجية التي يتم تنفيذها حاليًا إلى المتغير.
هناك نوعان من النطاق: النطاق الثابت والنطاق الديناميكي .
النطاق الثابت الذي يستخدمه JS يسمى أيضًا "النطاق المعجمي". يتم تحديد نطاق الوظيفة عند تعريف الوظيفة.
مما سبق، سيكون للمتغيرات في النطاق المعجمي نطاق معين أثناء عملية التجميع. هذا النطاق هو "سياق التنفيذ الحالي". بعد ES5 نستخدم "البيئة المعجمية" بدلاً من النطاق لوصف سياق التنفيذ. تتكون البيئة المعجمية من عضوين:
دعونا نلقي نظرة على مثال:
قيمة var=1 ؛وظيفة فو(){ console.log(value);}شريط الوظائف(){ قيمة فار = 2؛ foo();}bar();
بالنظر إلى التعريف أعلاه، ما الذي يجب طباعته؟
دعونا نحلل عملية التنفيذ:
قم بتنفيذ الدالة foo()، وقم أولاً بالبحث داخل الدالة foo لمعرفة ما إذا كانت هناك قيمة متغيرة محلية. إذا لم يكن الأمر كذلك، فابحث عن الكود الموجود في الطبقة العليا استنادًا إلى الموضع الذي تم تعريفه فيه، أي القيمة = 1، وبالتالي ستتم طباعة النتيجة على أنها 1.
بالطبع، هذا ليس بهذه البساطة ويمكن تلخيصه من منظور سياق التنفيذ.
تحدثنا أعلاه عن مكوني البيئة المعجمية (النطاق). بالاقتران مع سياق التنفيذ، ليس من الصعب العثور على أنه من خلال مرجع البيئة المعجمية الخارجية، يمكن توسيع النطاق على طول طبقة المكدس بطبقة، مما يؤدي إلى إنشاء هيكل سلسلة يمتد إلى الخارج من البيئة الحالية.
دعونا نلقي نظرة على مثال آخر:
function foo(){ console.dir(bar); فار أ=1; شريط الوظائف () { أ=2; }}console.dir(foo);foo();من النطاق الثابت، تقوم الدالة العامة foo بإنشاء سمة [[scope]
]
[[scope]]
الخاص بها
foo[[scope]]=[globalContext];
( )، فإنه سيدخل أيضًا فترة التعريف وفترة التنفيذ للدالة foo على التوالي.
خلال فترة تعريف الدالة foo، سيتضمن [[نطاق]] شريط الوظائف النطاق العامالمدمج
[[scope]]
المدمج لـ foo
bar[[scope]]=[fooContext,globalContext];
هذه النقطة: "سوف تمر JS بمراجع البيئة المعجمية الخارجية لإنشاء سلسلة نطاق من الكائنات المتغيرة، وبالتالي ضمان الوصول المنظم إلى المتغيرات والوظائف التي يمكن لبيئة التنفيذ الوصول إليها."
دعنا نعود إلى السؤال في سياق التنفيذ، قلنا سابقًا ما الفرق بينهما؟ لنتحدث عن سبب طباعة "النطاق المحلي" بنفس الطريقة: لا تزال نفس الجملة "يستخدم JS النطاق المعجمي، ويعتمد نطاق الوظيفة على الموقع الذي تم إنشاء الوظيفة فيه. " - تنفيذ وظيفة JS يتم استخدام سلسلة النطاق، والتي يتم إنشاؤها عند تعريف الوظيفة. يتم تعريف الوظيفة المتداخلة f() في سلسلة النطاق هذه، ويجب أن يشير نطاق المتغير فيها إلى المتغيرات المحلية. بغض النظر عن وقت ومكان تنفيذ f()، يظل هذا الارتباط صالحًا عند تنفيذ f().
عندما لا يمكن العثور على متغير في سجل البيئة المعجمية الخاصة به، يمكن البحث عنه في الطبقة الخارجية بناءً على مرجع البيئة المعجمية الخارجية حتى يصبح مرجع البيئة المعجمية الخارجية في البيئة المعجمية الخارجية null
.
يشبه هذا "البحث بناءً على سلسلة النموذج الأولي في الكائنات":
__proto__
خالٍ)والفرق واضح أيضًا: سلسلة النموذج الأولي هي رابط يؤسس وراثة الكائن من خلال سمة النموذج الأولي، بينما تشير سلسلة النطاق إلى الإغلاق الذي يسمح للوظائف الداخلية بالوصول إلى الوظائف الخارجية. سواء بشكل مباشر أو غير مباشر، ترتبط جميع سلاسل نطاق الوظائف في النهاية بالسياق العالمي.
التوصيات ذات الصلة: البرنامج التعليمي لتعلم JavaScript
ما ورد أعلاه هو فهم متعمق لكيفية تنفيذ محرك JavaScript لرمز JS. لمزيد من المعلومات، يرجى الانتباه إلى المقالات الأخرى ذات الصلة على موقع PHP الصيني!