واحدة من أهم الميزات في JavaScript هي استخدام الإغلاق. بسبب استخدام الإغلاق ، يمكن للنطاق الحالي دائمًا الوصول إلى نطاقات خارجية. نظرًا لأن JavaScript ليس له نطاق على مستوى الكتلة ونطاق الوظيفة فقط ، فإن استخدام الإغلاق يرتبط ارتباطًا وثيقًا بالوظائف.
محاكاة المتغيرات الخاصة
نسخة الكود كما يلي:
وظيفة عداد (ابدأ) {
var count = start ؛
يعود {
الزيادة: وظيفة () {
count ++ ؛
} ،
الحصول على: وظيفة () {
عدد العائد
}
}
}
var foo = counter (4) ؛
foo.increment () ؛
foo.get () ؛ // 5
هنا العداد يعيد اثنين من الإغلاق: زيادة الوظيفة والحصول. تحافظ هاتان الوكبتان على الوصول إلى نطاق العداد ، بحيث يمكنهما الوصول إلى العد المتغير المحدد في نطاق العد.
آلية العمل للمتغيرات الخاصة
نظرًا لأن JavaScript لا يمكنه تعيين القيم والإشارات إلى النطاقات ، في المثال أعلاه ، لا توجد طريقة للوصول مباشرة إلى عدد المتغيرات الخاصة الداخلية من الخارج. الطريقة الوحيدة هي الوصول إليها من خلال تحديد الإغلاق.
نسخة الكود كما يلي:
var foo = عداد جديد (4) ؛
foo.hack = function () {
العد = 1337 ؛
} ؛
لا يغير الرمز أعلاه قيمة متغير العد ضمن نطاق العداد ، لأنه لم يتم تعريف الاختراق داخل العداد. سوف يقوم الرمز أعلاه بإنشاء أو الكتابة فوق العد المتغير العالمي.
الإغلاق في الحلقة
واحدة من أسهل الأخطاء هو استخدام عمليات الإغلاق داخل حلقة.
نسخة الكود كما يلي:
لـ (var i = 0 ؛ i <10 ؛ i ++) {
setTimeout (function () {
console.log (i) ؛
} ، 1000) ؛
}
لن يتم إخراج الرمز أعلاه من 0 إلى 9 ، ولكنه سوف يخرج 10 مرات بشكل مستمر.
ستعمل عدم الكشف عن هويته أعلاه على الإشارة إلى المتغير i. عندما يتم استدعاء وظيفة console.log لبدء الإخراج ، فهذه هي الحلقة التي انتهت ، والمتغير I بالفعل 10.
لتجنب الخطأ أعلاه ، نحتاج إلى إنشاء نسخة من المتغير الذي أقدره في كل مرة نقوم بها.
تجنب أخطاء الاقتباس
لنسخ قيمة المتغير في الحلقة ، فإن أفضل طريقة هي إضافة وظيفة مجهولة إلى الطبقة الخارجية وتنفيذها على الفور.
نسخة الكود كما يلي:
لـ (var i = 0 ؛ i <10 ؛ i ++) {
(وظيفة (ه) {
setTimeout (function () {
console.log (e) ؛
} ، 1000) ؛
})(أنا)؛
}
تأخذ هذه الدالة الخارجية المجهولة متغير الحلقة I كمعلمة أول وتنسخ قيمتها إلى المعلمة الخاصة بها.
تمرر الدالة الخارجية المجهول المعلمة E إلى setTimeOut ، لذلك لدى SetTimeOut إشارة إلى المعلمة e. علاوة على ذلك ، لن تتغير قيمة هذه المعلمة E بسبب تغييرات الحلقة الخارجية.
هناك طريقة أخرى لتحقيق نفس التأثير ، وهو إرجاع وظيفة مجهولة في الدالة المجهولة في setTimeout:
نسخة الكود كما يلي:
لـ (var i = 0 ؛ i <10 ؛ i ++) {
setTimeout ((وظيفة (e) {
وظيفة الإرجاع () {
console.log (e) ؛
}
}) (ط) ، 1000)
}
بالإضافة إلى ذلك ، يمكن أيضًا تحقيقه من خلال طريقة الربط.
نسخة الكود كما يلي:
لـ (var i = 0 ؛ i <10 ؛ i ++) {
setTimeOut (console.log.bind (Console ، i) ، 1000) ؛
}
في نهاية المقالة ، دعونا نلخص:
(1) الإغلاق هو مبدأ التصميم. إنه يبسط مكالمات المستخدم عن طريق تحليل السياق ، مما يسمح للمستخدم بتحقيق هدفه دون معرفة ذلك ؛
(2) تتناقض المقالات الرئيسية على الإنترنت حول تحليل الإغلاق في الواقع مع مبدأ الإغلاق. إذا كنت بحاجة إلى معرفة تفاصيل الإغلاق لاستخدامها بشكل جيد ، فإن هذا الإغلاق هو فشل في التصميم ؛
(3) حاول أن تتعلم أقل قدر ممكن.