将局部变量传递给回调函数

时间:2010-12-16 22:42:34

标签: javascript scope prototypejs

问题

回调函数如何保留创建它的局部变量?

简单示例

我正在创建一个视频播放器。它将有滑块来控制饱和度,对比度和色调。当用户使用滑块时,它需要确认哪个滑块已更改以及更改了哪个值。问题是滑块的名称是来自此onChange回调的创建者范围的局部变量。该回调如何保留滑块的名称?

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 个答案:

答案 0 :(得分:9)

为每个回调创建变量的副本,您可以使用传递值的匿名函数执行此操作:

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
}

这样,您不会引用相同的i次X次。

答案 1 :(得分:7)

同一个变量i - 谁的值最终为4 - 与你在循环中创建的每个函数绑定。您可以将该函数包装在您当场调用的另一个函数中,并将i作为参数传递给该函数:

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)
 }
}

答案 2 :(得分:0)

以这种方式将你的函数放在一个闭包中:


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)
}