var foo = "hello" ؛ var c = (function a () {function b () {var bar = "world" ؛ alert (foo + bar) ؛ return bar ؛} return b ؛}) () () ؛ Alert (foo + c) ؛هذا المثال ينبثق Hello World مرتين ؛
1. ما هو الإغلاق؟
التفسير "الرسمي" هو: ما يسمى "الإغلاق" يشير إلى تعبير (عادةً ما يكون له وظيفة) له العديد من المتغيرات وبيئة مرتبطة بهذه المتغيرات ، وبالتالي فإن هذه المتغيرات هي أيضًا جزء من التعبير.
أعتقد أن قلة من الناس يمكنهم فهم هذه الجملة مباشرة لأنه وصفها أكاديميًا أيضًا. أرغب في استخدام كيفية إنشاء إغلاق في JavaScript لأخبرك ما هو الإغلاق ، لأنه من الصعب للغاية فهم تعريف الإغلاق مباشرة عن طريق تخطي عملية إنشاء الإغلاق. انظر إلى الكود التالي:
الدالة a () {var i = 0 ؛ function b () {Alert (++ i) ؛} return b ؛} var c = a () ؛ c () ؛هذا الرمز له خصائصان:
1. الوظيفة B متداخلة داخل الوظيفة A ؛
2. وظيفة A الإرجاع دالة ب.
وبهذه الطريقة ، بعد تنفيذ var c = a () ، يشير المتغير C فعليًا إلى الوظيفة b. بعد تنفيذ C () ، ستظهر نافذة لعرض قيمة I (المرة الأولى هي 1). هذا الرمز يخلق في الواقع إغلاق. لماذا؟ نظرًا لأن الوظيفة الخارجية C الخارجي A تشير إلى الوظيفة B داخل الوظيفة A ، أي::
عندما يتم الرجوع إلى الوظيفة الداخلية B للدالة A بواسطة وظيفة خارجية متغيرة ، يتم إنشاء إغلاق.
أعتقد أنك لا تزال لا تفهم عمليات الإغلاق لأنك لا تعرف ما هي عمليات الإغلاق. دعنا نستمر في الاستكشاف أدناه.
2. ما هي وظيفة الإغلاق؟
باختصار ، تتمثل وظيفة الإغلاق في أنه بعد تنفيذ A وإعادته ، يجعل الإغلاق آلية جمع القمامة JavaScript GC لا تسترد الموارد التي تحتلها A ، لأن تنفيذ وظيفة داخلية B من يحتاج إلى الاعتماد على المتغيرات في A. هذا وصف مباشر للغاية لدور الإغلاق ، وهو ليس مهنيًا أو صارمًا ، ولكنه يعني تقريبًا ذلك. فهم الإغلاق يتطلب عملية تدريجية.
في المثال أعلاه ، بعد إرجاع الوظيفة A ، أنا موجود دائمًا ، لذلك في كل مرة يتم تنفيذ C () ، أنا قيمة ISTED بعد إضافة 1.
ثم دعونا نتخيل موقفًا آخر. إذا كانت A لا تعمل ب ، فإن الموقف مختلف تمامًا. لأنه بعد تنفيذ A ، لا يتم إرجاع B إلى العالم الخارجي لـ A ، ولكن يتم الإشارة إليه فقط من قبل A ، وفي هذا الوقت سوف تتم الإشارة إلى A فقط من قبل B ، لذلك تتم الإشارة إلى الوظائف A و B إلى بعضها البعض ولكن لا يتم إزعاجها من قبل العالم الخارجي (المشار إليها من قبل العالم الخارجي) ، يتم إعادة تدوير الوظائف A و B بواسطة GC. (سيتم تقديم آلية جمع القمامة في JavaScript بالتفصيل لاحقًا)
3. العالم المجهري في الإغلاق
إذا كنا نريد أن يكون لدينا فهم أعمق للعلاقة بين الإغلاق والوظيفة A والوظيفة المتداخلة B ، فنحن بحاجة إلى إدخال العديد من المفاهيم الأخرى: بيئة تنفيذ الوظيفة (سياق الإثارة) ، والكائن النشط (كائن الاتصال) ، والنطاق (النطاق) ، وسلسلة النطاق. خذ عملية الوظيفة A من التعريف إلى التنفيذ كمثال لتوضيح هذه المفاهيم.
1. عند تحديد الوظيفة A ، سيقوم مترجم JS بتعيين سلسلة نطاق الوظيفة A إلى "البيئة" حيث توجد A عند تحديد A. إذا كانت A وظيفة عالمية ، فهناك فقط كائنات نافذة في سلسلة النطاق.
2. عند تنفيذ الوظيفة A ، ستدخل A بيئة التنفيذ المقابلة (سياق الإثارة).
3. في عملية إنشاء بيئة تنفيذ ، ستضيف أولاً سمة نطاق ، أي نطاق A ، وقيمتها هي سلسلة النطاق في الخطوة 1. أي سلسلة نطاق A.Scope = a.
4. ستقوم بيئة التنفيذ بإنشاء كائن نشط (كائن الاتصال). الكائن النشط هو أيضًا كائن ذو سمات ، ولكنه لا يحتوي على نموذج أولي ولا يمكن الوصول إليه مباشرة من خلال رمز JavaScript. بعد إنشاء الكائن النشط ، أضف الكائن النشط إلى أعلى سلسلة نطاق A. في هذا الوقت ، تحتوي سلسلة نطاق A على كائنين: الكائن النشط لكائن A و Window.
5. الخطوة التالية هي إضافة سمة وسيطات إلى الكائن النشط ، والذي يحفظ المعلمات التي تم تمريرها عند استدعاء الدالة A.
6. أخيرًا ، أضف جميع المعلمات الرسمية للدالة A والمراجع إلى الوظيفة الداخلية B إلى الكائن النشط لـ A. في هذه الخطوة ، يتم الانتهاء من تعريف الوظيفة B ، حتى في الخطوة 3 ، يتم تعيين سلسلة نطاق الوظيفة B على البيئة المحددة بواسطة B ، أي نطاق A.
في هذه المرحلة ، يتم الانتهاء من الوظيفة A بأكملها من التعريف إلى التنفيذ. في هذا الوقت ، تُرجع A مرجعًا إلى الوظيفة B إلى C ، وتتضمن سلسلة نطاق الوظيفة B مرجعًا إلى الكائن النشط للوظيفة A ، أي أن B يمكنه الوصول إلى جميع المتغيرات والوظائف المحددة في A. تتم الإشارة إلى الوظيفة B بواسطة C ، وتعتمد الوظيفة B على الوظيفة A ، لذلك لن يتم إعادة تدوير الوظيفة A بواسطة GC بعد إرجاعها.
عند تنفيذ الوظيفة B ، سيكون أيضًا كما هو مذكور أعلاه. لذلك ، تحتوي سلسلة نطاق B أثناء التنفيذ على 3 كائنات: الكائن النشط لـ B ، والكائن النشط لكائن A و Window ، كما هو موضح في الشكل أدناه:
كما هو موضح في الشكل ، عند الوصول إلى متغير في الوظيفة B ، فإن ترتيب البحث هو البحث أولاً عن كائنه النشط الخاص به ، وإذا كان موجودًا ، فسيعود. إذا لم يكن موجودًا ، فسيستمر في البحث عن الكائن النشط للوظيفة A ، والبحث بدوره حتى يتم العثور عليه. إذا كان لا يمكن العثور عليها في سلسلة النطاق بأكملها ، يتم إرجاع غير محدد. إذا كان هناك كائن النموذج الأولي للدالة B ، ثم بعد البحث عن كائنه النشط الخاص ، ابحث أولاً عن كائن النموذج الأولي الخاص به ، ثم استمر في البحث. هذه هي آلية البحث المتغيرة في JavaScript.
4. سيناريوهات التطبيقات
1. حماية أمن المتغيرات في الوظيفة. مع أخذ المثال الأول كمثال ، في الوظيفة A ، لا يمكن الوصول إلى الوظيفة B إلا من خلال الوظيفة B ، ولكن لا يمكن الوصول إليها من خلال قنوات أخرى ، وبالتالي حماية أمان I.
2. الحفاظ على متغير في الذاكرة. لا يزال كما كان من قبل ، بسبب الإغلاق ، أنا في الوظيفة A دائمًا في الذاكرة ، لذلك في كل مرة يتم تنفيذ C () ، سيتم إضافتي 1.
النقطتان أعلاه هما سيناريوهات التطبيق الأساسية للإغلاق ، وتنشأ العديد من الحالات الكلاسيكية من هذا.
5. آلية جمع القمامة JavaScript
في JavaScript ، إذا لم يعد هناك كائن ما ، فسيتم إعادة تدوير الكائن بواسطة GC. إذا تمت الإشارة إلى كائنين لبعضهما البعض ولم يعد يتم الإشارة إليهما من قبل الشخص الثالث ، فسيتم إعادة تدوير الكائنين المشار إليهما إلى بعضهما البعض. نظرًا لأنه يتم الرجوع إلى الوظيفة A بواسطة B ، يتم الرجوع B بواسطة C خارج A ، وهذا هو السبب في أن الوظيفة A لن يتم إعادة تدويرها بعد التنفيذ.
إن المقالة أعلاه تتفهم بشكل شامل أن آلية الإغلاق هي كل المحتوى الذي أشاركه معك. آمل أن تتمكن من إعطائك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.