Pass in local variable to callback function [dupli

2019-04-20 03:19发布

This question already has an answer here:

Question

How can a callback function retain a local variable from whence it was created?

Simple example

I'm creating a video player. It will have sliders to control the saturation, contrast, and hue. When the user plays with the sliders, it needs to acknowledge which slider got changed and what value it got changed to. The problem is that the name of the slider is a local variable from the scope of the creator of this onChange callback. How can this callback retain the name of the slider?

HTML

<div id="saturation">
 <div class="track"></div>
  <div class="knob"></div>
 </div>
</div>

<div id="contrast">
 <div class="track"></div>
  <div class="knob"></div>
 </div>
</div>

<div id="hue">
 <div class="track"></div>
  <div class="knob"></div>
 </div>
</div>

JS

var elements = [
 'saturation',
 'contrast',
 'gamma'
];

for(var i = 0; i < sliders.size(); i++) {
 new Control.Slider(
  $(elements[i]).down('.knob'),
  $(elements[i]).down('.track'), {
   onChange: function(value) {
    // ERROR: elements[i] is undefined
    alert(elements[i] + ' has been changed to ' + value);
   }
 }
}

3条回答
混吃等死
2楼-- · 2019-04-20 03:53

The same variable, i — who's value ends up being 4 — is bound to every function you create inside the loop. You could wrap the function in another function that you call on the spot and pass i as a parameter to that function:

for(var i = 0; i < sliders.size(); i++) {
 new Control.Slider(
  $(elements[i]).down('.knob'),
  $(elements[i]).down('.track'), {
   onChange: (function(inner_i) { function(value) {
    alert(elements[inner_i] + ' has been changed to ' + value);
   } })(i)
 }
}
查看更多
老娘就宠你
3楼-- · 2019-04-20 04:14

Create a copy of the variable for each callback, you can do this with an anonymous function that you pass in the value:

for(var i = 0; i < sliders.size(); i++) {

    (function(e) { // get a local copy of the current value

        new Control.Slider(
          $(elements[e]).down('.knob'),
          $(elements[e]).down('.track'), {
           onChange: function(value) {
            // ERROR: elements[e] is undefined
            alert(elements[e] + ' has been changed to ' + value);
           }
         }

     })(i); // pass in the current value
}

This way you don't reference the same i X times.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-04-20 04:14

Put your function inside a closure in this way:


for(var i = 0; i < sliders.size(); i++) {
 (function(q){
 new Control.Slider(
  $(elements[q]).down('.knob'),
  $(elements[q]).down('.track'), {
   onChange: function(value) {
    // ERROR: elements[q] is undefined
    alert(elements[q] + ' has been changed to ' + value);
   }
 }
 })(i)
}
查看更多
登录 后发表回答