2011-07-29 11 views
0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    <title>Ovi Maps API Example</title> 

    </head> 
    <body> 
     <button id="butt1" name="butt" type="button">Click Me!</button> 
     <button id="butt2" name="butt" type="button">Click Me!</button> 
     <button id="butt3" name="butt" type="button">Click Me!</button> 
    </body> 
    <script src="jquery.js" type="text/javascript" charset="utf-8"></script> 
    <script src="foo.js" type="text/javascript" charset="utf-8"></script> 
</html> 

と...なぜこのhtml/javascriptコンボは、それがどうやって印刷するのですか?

$(document).ready(function() { 
//alert("ready"); 
var myClickFunctions = new Array(); 

//add event handlers to all three buttons 
for(var i=1;i<=3;i++){ 

    myClickFunctions[i]=function(){ 
    var index = i; 
    alert(index); 
    } 

    var buttonID = "#butt"; 
    var button = $(buttonID + i);  
    button.click(myClickFunctions[i]); 
} 

})。

すべてのボタンが印刷されます4.これはなぜ、ハンドラが作成されたiの値をそれぞれに印刷するための良い方法ですか?

答えて

4

JavaScriptのクロージャとその仕組みについての説明を読んでください。事実は、button.click(myClickFunctions[i]);iは、最後に4になるでしょう。関数が宣言されているときは、var index = iが設定されていないことを覚えておいてください。これを行う、いっそ

myClickFunctions[i]=(function(i){ 
    return function(){ 
     var index = i; 
     alert(index); 
    } 
    })(i) 

かを::

//put this anywhere 
function myClickFunctions(i){ 
    return function(){ 
    alert(i); 
    } 
} 

//and at the end: 
button.click(myClickFunctions(i)); 

myClickFunctions機能は、iの現在の値を取る、と返す何をする必要があるので、同様に閉鎖で関数をラップしていますその値がすでに設定されています。それがこれを行う正しい方法です。

+0

迅速な対応に感謝します。私は閉鎖に漠然と慣れています。私が欠けていたキーは、関数が呼び出されるまで可変インデックスが設定されていないということでした。 – nsfyn55

0

関数がループするたびに同じ変数に新しい値を割り当てるので、任意のボタンをクリックするとvarインデックスが4になります。

次のようなもの添付するだろうそのインデックスを各アンカータグの印刷を行うことへの迅速なアプローチ:私はこれを見ることができます

$('a').click(function() { 
    var theAnchors = $('a'); 
    for (i in theAnchors) 
     if (theAnchors[i] == this) 
      alert(i); 
}); 

唯一の問題は、私は、オブジェクト等価比較のみに検証しないだろうということです比較されている2つのDOM要素がまったく同じですが、可能である場合はtrueです。

さらに、ここで達成しようとしている最終目標は何ですか(アンカーをクリックするとアラートを表示するユーザーを嫌うページを作成するのは、最終目標ではありません)。

+0

ありがとうございます、詳細をお知らせください。私の脳の働き方は、スコープチェインの仕組みのせいで、私の参照はすべての機能の間で共有されているからです。 – nsfyn55

+0

Javascriptの可変スコープに関してもっとお手伝いしたいと思いますが、私は専門家ではありません。私は他の多くの言語に比べて比較的奇抜であると言うことは十分に知っていますが、あなたがしようとしていることについてより良い記述があれば、私はあなたを助けることができるかもしれません。 – MoarCodePlz

+1

JavaScriptの 'for ... in'ループを使用すると、予期しない結果につながる可能性があります。アイテムを順番にループするという保証はなく、継承されたプロパティを扱うという問題もあります。ループの標準が良いでしょう。ページに多数のアンカーがある場合、これはまた潜在的に高価です。 –

2

myClickFunctions[i]に設定している無名関数は、iの周りにクロージャを作成しています。クローズは、クロージャが作成された時点の値ではなく、変数自体で終了します。したがって、関数が実際に実行されるときには、iは4なので、常に4になります。

単純な修正は、関​​数を返す関数を呼び出し、iの現在の値を取得することです。

myClickFunctions[i] = (function(curI) { 
    return function() { 
     var index = curI; 
     alert(index); 
    }; 
})(i); 

これが混乱する場合は、JavaScriptでクロージャを読むことをおすすめします。彼らはしばらくすると第二の性質になる。

0

ループ終了時の "i"の値は "4"なので、ボタンをクリックするたびに "i"の参照にアクセスしているためにあなたに表示される数字は "4"ループ中ではなくボタンをクリックすると関数が実行されています。

"i"の番号を取得したい場合は、ボタンのidと同じですので、これを行うことをお勧めします。

$(document).ready(function() { 
//alert("ready"); 
var myClickFunctions = new Array(); 

//add event handlers to all three buttons 
for(var i=1;i<=3;i++){ 

    myClickFunctions[i]=function(){ 
    var id = $(this).attr('id'); 
    var index = id.replace('butt', ''); 
    alert(index); 
    } 

    var buttonID = "#butt"; 
    var button = $(buttonID + i);  
    button.click(myClickFunctions[i]); 
} 

});