2010-12-16 7 views
10

質問パスは、コールバック関数する

はどのようにコールバック関数は、それが作成されたそこからローカル変数を保持することができますか?

簡単な例

私はビデオプレーヤーを作成しています。彩度、コントラスト、色相をコントロールするスライダがあります。ユーザーがスライダーを操作するとき、どのスライダーが変更されたのか、どのスライダーに変更されたのかを確認する必要があります。問題は、スライダの名前がこの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); 
    } 
} 
} 

答えて

6

同じ変数、i - 値だ4をされて終わる - あなたがループ内で作成するすべての関数にバインドされています。あなたはその匿名関数でこれを行うことができ、各コールバックのための変数のコピーを作成します

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

これは私の構文エラーを与えました。 – JoJo

+3

これは正しいことだと思います。 onChange:function(){ return function(value){ alert(elements [i] + value); } }(要素[i]) – JoJo

+0

これを見て、著者はreturn文を省略して賢明だと思った。 Lispのような言語はデフォルトで最後の式を返すだけです。残念ながらjavascriptはそれらの1つではありません:( –

8

:あなたはその場で呼び出すと、その関数のパラメータとしてiを渡す別の関数で関数をラップすることができあなたは値を渡す:

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回を参照しません。

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