كيف أقوم بتمرير القيمة (وليس المرجع) لمتغير JS إلى وظيفة؟ [مكرر

StackOverflow https://stackoverflow.com/questions/2568966

سؤال

هذا السؤال لديه بالفعل إجابة هنا:

إليك نسخة مبسطة من شيء أحاول تشغيله:

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
        change_selection(i);
    }); 
}

لكنني أجد أن كل مستمع يستخدم قيمة النتائج. الطول (القيمة عندما تنتهي الحلقة). كيف يمكنني إضافة مستمعين بحيث يستخدم كل منهم قيمة I في الوقت الذي أضيفه فيه ، بدلاً من الإشارة إلى I؟

هل كانت مفيدة؟

المحلول

في المتصفحات الحديثة ، يمكنك استخدام let أو const الكلمات الرئيسية لإنشاء متغير مكتوفي:

for (let i = 0; i < results.length; i++) {
  let marker = results[i];
  google.maps.event.addListener(marker, 'click', () => change_selection(i));
}

في المتصفحات القديمة ، تحتاج إلى إنشاء نطاق منفصل يحفظ المتغير في حالته الحالية عن طريق تمريره كمعلمة دالة:

for (var i = 0; i < results.length; i++) {
  (function (i) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
      change_selection(i);
    }); 
  })(i);
}

من خلال إنشاء وظيفة مجهولة ووصفها بالمتغير كوسيطة أول ، فأنت تمر بالقيمة إلى الوظيفة وإنشاء إغلاق.

نصائح أخرى

وكذلك الإغلاق ، يمكنك استخدام function.bind:

google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));

يمر قيمة i في حجة إلى الوظيفة عند استدعاء. ((null هو للربط this, ، وهو ما لا تحتاجه في هذه الحالة.)

function.bind تم تقديمه بواسطة إطار النموذج الأولي وتم توحيده في الطبعة الخامسة ECMASCRIPT. حتى تدعم المستعرضات جميعها أصليًا ، يمكنك إضافة خاصة بك function.bind الدعم باستخدام الإغلاق:

if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}

الإغلاق:

for (var i = 0, l= results.length; i < l; i++) {
    marker = results[i];
    (function(index){
        google.maps.event.addListener(marker, 'click', function() { 
            change_selection(index);
        }); 
    })(i);
}

تحرير ، 2013:يشار إليها الآن باسم iife

أنت تنتهي بإغلاق. هذا مقال عن الإغلاق وكيفية العمل معهم. تحقق من المثال 5 على الصفحة ؛ هذا هو السيناريو الذي تتعامل معه.

تحرير: بعد أربع سنوات ، هذا الرابط قد مات. جذر القضية أعلاه هو أن for إغلاق أشكال الحلقة (على وجه التحديد على marker = results[i]). مثل marker يتم تمريرها addEventListener, ، ترى التأثير الجانبي للإغلاق: يتم تحديث "البيئة" المشتركة مع كل تكرار للحلقة ، قبل أن يتم "حفظها" أخيرًا عبر الإغلاق بعد التكرار النهائي. MDN يشرح هذا جيدا جدا.

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', (function(i) {
        return function(){
            change_selection(i);
        }
    })(i)); 
}

أعتقد أنه يمكننا تحديد متغير مؤقت لتخزين قيمة i.

for (var i = 0; i < results.length; i++) {
 var marker = results[i];
 var j = i;
 google.maps.event.addListener(marker, 'click', function() { 
   change_selection(j);
 }); 
}

لم أختبرها رغم ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top