dポイントプレゼントキャンペーン実施中!

-----
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>

<script type='text/javascript'>
(function(){
var li = document.getElementsByTagName('li');

for(var i=0,max=li.length; i<max; i++){
li[i].onclick = function(){
alert(i);
};
}
})();
</script>
-----

上記スクリプトを実行すると、全てのli要素でクリックしたときに "3" がalertされます。
0,1,2 をそれぞれalertしたいのですが、どういった方法が考えられるでしょうか?

現在作成しているスクリプトでは、下記のようにidに値を保持しています。
もう少しスマートな方法がある気がするのですが…。

---
li[i].id = 'test' + i;
li[i].onclick = function(){
alert(this.id.replace(/^test(\d+)/, '$1'));
};
---

A 回答 (11件中1~10件)

http://nanto.asablo.jp/blog/2005/12/04/165848
メモリーリークにみえて、そうでない・・・

>HTMLObjectに勝手にプロパティ
これはよくないことだじょ!そうおそわった。

ついでにいうと、いべんとをなんこもていぎするより
No3.みたいにおおもとにひとつでじゅうぶん。
innerHTMLで、ぜんたいをかきかえたとしてもOK!
と、TAGindex
http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi
でおそわったじょ!
    • good
    • 0
この回答へのお礼

参考URLの掲示ありがとうございます。

> メモリリーク
非常に難解で、まだ完全には理解できていないのですが、
「要素ノードとクロージャの間で循環的に参照(循環参照)してしまい、タブを閉じる際にIEがこれを解放しないためにリークする」
という理解でいいのでしょうか?

調査の結果、メモリリークの回避手段がいくつかあることがわかりました。

----
1. 関数をネストしない
HTML ページの DOM オブジェクトへの循環参照はメモリ リークが発生します。
http://support.microsoft.com/kb/830555/ja
IEのメモリリーク問題
http://p2b.jp/index.php?UID=1131336575

2. elementNode=null; で参照を外す
IE6のメモリリークを華麗に回避 - zorioの日記
http://d.hatena.ne.jp/zorio/20080609/1213028969

3. document一つをイベントリスナに登録し、クロージャを使わない (#3と同じ)
掲示板/JavaScript質問板/過去ログ/一覧/ onclik時に上部へ行く方法(特殊) - TAG index Webサイト
http://www.tagindex.com/kakolog/q4bbs/1301/1650. …

4. 使い終わったイベントハンドラを外す関数を定義する
クロージャとメモリリークについてのコピペ - JavaScriptとかPerlとかPHPとかさくらとか勉強する (>702の createLeakFreeClosure(closure) )
http://d.hatena.ne.jp/lesamoureuses/20080416/120 …
----

「循環の仕組み」が不完全な理解なので、「1=理解、2=何となく理解、3,4=理解不能」と心許ないのが現状です。
今のところ、2. を応用して

----
(function(){
var li = document.getElementsByTagName('li');

for(var i=0,max=li.length; i<max; i++){
li[i].onclick = (function(i){
return function(){// functionを返す(クロージャ)
alert(i);
};
})(i);

li[i] = null;// 要素ノードの参照を外す
}

})();
----

で運用しようと考えていますが、これで問題ないでしょうか?
また、間違って理解しているところはないでしょうか?
(曖昧な理解なだけに心配です…。)

お礼日時:2009/06/23 19:33

ごめん!かんちがい!


>li[i] = null; // 要素ノードの参照を外す
'}'のいち、みまちがえてました。

onclickをうわがきされると、うごかなくなるよ

この回答への補足

まだ理解がおぼつかないですが、引き延ばしても仕方がないのでこれにて締め切りたいと思います。
そこでまたわからないことがあれば質問するかもしれません。その時はよろしくお願いします。

ありがとうございました。

補足日時:2009/06/24 22:10
    • good
    • 0
この回答へのお礼

> onclickをうわがきされると、うごかなくなるよ
そうですね。
window.onload と同じく、同じ場所に上書きされると初めに登録したイベントが動かなくなります。
それは承知しているのですが、今回の場合同じ場所にonclickイベントを登録する意義が見あたらないのでいいかなと。

また、「コードはシンプルに」という点には拘ってまして、長いコードは出来るだけ避けたいという思いがあります。
でも、「イベントリスナを使う癖を付けておいた方が良いのでは」という気もしますし、
addEvent() 的な関数を使用して elementNode=null; がいいような気もします。

落としどころが難しく、悩みます…。

お礼日時:2009/06/23 21:40

たぶん、じぶんもよくりかいできていません。


ところで
>li[i] = null; // 要素ノードの参照を外す
は、なに?

そこまでよんで、なんでいべんといっぱいつけるかなぁ~^^;
    • good
    • 0
この回答へのお礼

いろいろとアドバイス有り難うございます。

> そこまでよんで、なんでいべんといっぱいつけるかなぁ~^^;
- #3を理解できていない
- コードが複雑化するのは避けたい

理解できてない、のが大きいです。
よくわからずに使って弊害が出てしまうのは本末転倒なので…。(苦笑)

お礼日時:2009/06/23 21:26

そもそも、「保持する」必要ありますか?


まぁリソースは有効活用したほうがいいですが・・・

<script type='text/javascript'>
window.onload=function(){
var li = document.getElementsByTagName('li');
for(var i=0; i<li.length; i++){
li[i].onclick = function(){
var li = document.getElementsByTagName('li');
for(var i=0;i<li.length;i++){
if(li[i]==this) break;
}
alert(i);
};
}
};
</script>

<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
    • good
    • 0
この回答へのお礼

> そもそも、「保持する」必要ありますか?
実際には要素ノードリストを2組持ち、iの値で2つを関連づけています。
関連付けの仕組みを変えればiが不要となるはずですが、アルゴリズムを根本から直す必要がありそうです。
ちなみに、http://vird2002.s8.xrea.com/test/dl2tab.html が実際のスクリプトです。

「同じノードを探し出す」
初めはそのようにしていましたが、そもそも一度捕まえたノードは再利用した方が効率がいいんじゃないか、と思い質問に至りました。

掲示されたコードはアプローチの一つとして参考にさせていただきます。
ありがとうございます。

お礼日時:2009/06/23 21:23

前々からできるかどうか不安だった方法を、この際だから調べてみました。


邪道かも。決していい方法であるとは思っていません。

ie8,FireFox,Operaで確認。(うまくいくのか・・・うれしいような残念なような・・・)
HTMLObjectに勝手にプロパティ追加してます。

<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>

<script type='text/javascript'>
window.onload=function(){
var li = document.getElementsByTagName('li');

for(var i=0,max=li.length; i<max; i++){
li[i].i=i
li[i].onclick = function(){alert(this.i);
};
}
}
</script>
    • good
    • 0
この回答へのお礼

> HTMLObjectに勝手にプロパティ追加してます。
こ、こんな方法があるとは…。
FirebugのDOMタブを見ると、「プロパティi」がちゃんと見えています。

IE7でも動きました。動いてしまうんですね…。

ちょっと怖くて使えそうにありませんが、興味深い現象でした。
ありがとうございます。

お礼日時:2009/06/22 21:58

window.onload = function (){


var li = document.getElementsByTagName('li');
for(var i=0,max=li.length; i<max; i++){
make_li_func(li[i],i);
}
}
function make_li_func(li,no){
var i=no+1;
var func=li;
func.onclick = function(){
alert(i);
}
}
で出来ました。
もしかして、原理はbabu_babueさんと同じかしら?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

新しくユーザ定義関数を定義したのですね。
もうちょっと簡略化して、

---
var li = document.getElementsByTagName('li');

function test(node,i){
node.onclick = function(){
alert(i);
};
}
for(var i=0,max=li.length; i<max; i++){
test(li[i],i);
}
---

でも出来ました。

> もしかして、原理はbabu_babueさんと同じかしら?
「引数で値を渡す」という発想はbabu_babueさんと同じだと思います。
無名関数に引数を渡すためにクロージャを使っていたところが違う部分ですね。

お礼日時:2009/06/22 21:48

>どのような情報が足りないでしょうか?



くろ~じゃ・めもりーりーく・じょうけんつきこんぱいる

えらそうなことをいえるほど、おおくをしらないので・・・
ばぶ~!
    • good
    • 0
この回答へのお礼

ありがとうございます。
キーワードだけでも参考になります。
質問当初の時点では「メモリーリーク」以外は知りませんでした。

なので、補足要求された情報は持ち合わせていなかったのだと思います。

お礼日時:2009/06/22 21:30

一例です。



<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>

<script type='text/javascript'>
(function(){
var li = document.getElementsByTagName('li');

for(var i=0,max=li.length; i<max; i++){
li[i].onclick = (function(j){
return function(){alert(j);}
})(i);

}
})();

解説は以下をご参照ください。
http://www.atmarkit.co.jp/fdotnet/ajaxjs/ajaxjs0 …
    • good
    • 0
この回答へのお礼

参考URLまでありがとうございます。
今読み終わったところです。

クロージャという仕組みを使っているのですね。
クロージャとは「関数を戻り値に持つ関数」で掲示されているコードでは
無名関数がクロージャとして機能している、と理解しました。
#1の方もクロージャを使われていたことから、クロージャを使う方法は広く使われているようだと想像できます。

理解が深まりました。ありがとうございます。

お礼日時:2009/06/22 21:27

//@cc_on


document./*@if(@_jscript)attachEvent('on'+ @else@*/addEventListener(/*@end@*/
 'click', function (evt) {
  var c = 0, e = evt./*@if(@_jscript) srcElement @else@*/ target /*@end@*/;

  if ('LI' == e.tagName) {
   while (e = e.previousSibling) if ('LI' == e.tagName) c++;
   alert(c);
  }
 }, false);
//ぜんかくくうはくは、てきとうになおしてね ばぶ~!
//これだといべんとを、はがしてないよね
    • good
    • 0
この回答へのお礼

なるほど、これが「条件付きコンパイル」なのですか。難しいですね…。

ありがとうございます。

お礼日時:2009/06/22 21:10

(function(){


var li = document.getElementsByTagName('li'), o, c = 0;
while (o = li[c]) o.onclick = (function(i){ return function() {alert(i);};})(c++);
})();
でも、メモリーリーク。

この回答への補足

ひょっとして、#2だけメモリリーク、でしょうか。

- #2でもメモリーリーク (#1,2の両方)
- こういうコートがあるけど、メモリーリーク (#2だけ)

見方によって、受け取り方が変わってしまいますね…。

補足日時:2009/06/22 21:02
    • good
    • 0
この回答へのお礼

何度もありがとうございます。

#1,2ともにメモリリークするコードと指摘されているのでしょうか…。
何のために#1からこのように変化したのかが理解できていません。(汗)

お礼日時:2009/06/22 21:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!