إغلاق جافا سكريبت ومثال على سلسلة النطاق
-
21-12-2019 - |
سؤال
هل يمكن لأحد أن يشرح لي (بشكل واضح وموجز) لماذا يعمل هذا الرمز بالطريقة التي يعمل بها؟لقد جئت من خلفية مكتوبة بقوة في Java (6 و 7) حيث لا توجد عمليات الإغلاق ولا تعمل بالطريقة التي تعمل بها في جافا سكريبت.أعتقد أن المفاهيم المتعلقة بهذا السؤال هي:عمليات الإغلاق وسلسلة النطاق.
إليك المثال:
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = function() { console.log(i); }
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
المثال أعلاه يسجل 9 (10 مرات)، ولكن التوقع وحدسي الخاص كان يعتقد أنه سيسجل 0-9.
لماذا يعمل هذا بالطريقة التي يعمل بها في Javascript؟عمليات الإغلاق قوية جدًا، لكنني أحاول استيعاب المفهوم مرة واحدة وإلى الأبد!مثال معدل قليلاً ينتج النتيجة الصحيحة، ولكن لماذا؟
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = (function(index) { console.log(index); })(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
عمليات الإغلاق ليست فريدة بالنسبة لجافا سكريبت، ولكني أريد أن أرى سبب قوتها في سياق كتابة جافا سكريبت فعليًا للتفاعل مع المتصفح/دوم.
هل لدى أي شخص أمثلة عملية جيدة لكيفية تطبيق تقنية الإغلاق عند التفاعل مع المتصفح/دوم؟
شكرًا.
المحلول
في الأمثلة التي لديك، الأمر بسيط جدًا.
في المثال الأول، هناك متغير واحد فقط i
وكل شيء يشير إلى تلك القيمة الواحدة.لذا..يقوم بطباعة الرقم 9
عشرة مرات.تم التقاط كل وظيفة أ مشترك قيمة ال i
هذا يتغير.
في المثال الثاني، تستخدم الإغلاق.تحتوي كل دالة على متغير خاص يسمى index
الذي يستقبل -- وهنا الجزء المهم -- أ ينسخ من القيمة i
.
لذلك، تحصل 0
خلال 9
لأن هناك عشر وظائف، لكل واحدة منها خصوصية index
متغير وكل واحد من هؤلاء index
المتغيرات الحصول على لقطة من i
كما كانت موجودة في ذلك الوقت.
قد يساعد هذا الشكل الأطول من الإغلاق على:
function myFactory(index) {
return function() {
console.log(index);
}
}
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = myFactory(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });