いつか絶対に引っかかるというJavaScriptの予言が的中した
「ん? 変数の値が上書きされてる!」
「あれー。なんかループの中のデータがおかしい!」とか、「ん?変数の値が上書きされてる!」とかいう事態が起きたら、この投稿を思い出してください。
予言しよう!あなたはいつか、この罠を踏む。
いつかあなたが絶対に引っかかる、ある一つのJavaScriptの罠 - Qiita
「あれー。なんかループの中のデータがおかしい!」とか、「ん?変数の値が上書きされてる!」とかいう事態が起きたら、この投稿を思い出してください。
予言しよう!あなたはいつか、この罠を踏む。
いつかあなたが絶対に引っかかる、ある一つのJavaScriptの罠 - Qiita
ついに引っかかってしまった。
class Trap
constructor: ->
@prefix = '#btn-'
@types = ['hoge', 'hage', 'fuge']
@bind @types
bind: (types) ->
for type in types
$(@prefix + type).click =>
@setType(type)
setType: (type) ->
console.log "Set #{type}."
これを実行すると、どのボタンをクリックしても結果がSet fuge.
になってしまう。
よくある失敗の例だ。ループの中で関数を定義しているわけだが、ループ変数は関数の外部で定義されている。クリックしたときに実行する関数は、実行時に i を参照するが、それはループが終わったときの値だ。従って、今回の例の場合は3が表示される。
JavaScript のクロージャとループ、変数について | UB Lab.
回避方法
ループ内で関数を定義していて、ループ変数の値を表示するには、関数を戻す関数を定義する必要がある。下記の例では、クリックしたときに実行される関数は、関数を戻しており、かつ、関数自体を呼び出すように指定して引数にループ変数を渡している。console.log で渡している引数は、最初の関数の引数と同じものを参照するので、ループしている間の i の値を表示することができる。
for(var i = 0; i < array.length; i++) {
array[i].click((function(n) {
return function() {
console.log(n);
}
}).call(this, i));
}
これCoffeeScriptでどうやって書くの?
ループ内で関数を定義していて、ループ変数の値を表示するには、関数を戻す関数を定義する必要がある。下記の例では、クリックしたときに実行される関数は、関数を戻しており、かつ、関数自体を呼び出すように指定して引数にループ変数を渡している。console.log で渡している引数は、最初の関数の引数と同じものを参照するので、ループしている間の i の値を表示することができる。
for(var i = 0; i < array.length; i++) {
array[i].click((function(n) {
return function() {
console.log(n);
}
}).call(this, i));
}
2015-08-24 更新
bind: (types) ->
for type in types
do (type) =>
$(@prefix + type).click =>
@setType(type)
@pomutemuさんがコメントで綺麗な書き方を教えてくださったので、内容を更新しました! codepenライブデモ
以下旧版
デザイナー崩れの脳味噌では上手く書けなかったので便利なツールに頼ることにした。
bind: (types) ->
for type in types
$(@prefix + type).click ((t) =>
=>
@setType t
).call @, type
これで無事、ループ内の変数をコールバックの引数に渡すことができた。
Author And Source
この問題について(いつか絶対に引っかかるというJavaScriptの予言が的中した), 我々は、より多くの情報をここで見つけました https://qiita.com/y_hokkey/items/e07769d6aea2e194ead2著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .