• ベストアンサー

for(var i=0;...) の i の値を保持するには?

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

質問者が選んだベストアンサー

  • ベストアンサー
回答No.8

http://nanto.asablo.jp/blog/2005/12/04/165848 メモリーリークにみえて、そうでない・・・ >HTMLObjectに勝手にプロパティ これはよくないことだじょ!そうおそわった。 ついでにいうと、いべんとをなんこもていぎするより No3.みたいにおおもとにひとつでじゅうぶん。 innerHTMLで、ぜんたいをかきかえたとしてもOK! と、TAGindex http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi でおそわったじょ!

think49
質問者

お礼

参考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.html 4. 使い終わったイベントハンドラを外す関数を定義する クロージャとメモリリークについてのコピペ - JavaScriptとかPerlとかPHPとかさくらとか勉強する (>702の createLeakFreeClosure(closure) ) http://d.hatena.ne.jp/lesamoureuses/20080416/1208325055 ---- 「循環の仕組み」が不完全な理解なので、「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; // 要素ノードの参照を外す } })(); ---- で運用しようと考えていますが、これで問題ないでしょうか? また、間違って理解しているところはないでしょうか? (曖昧な理解なだけに心配です…。)

その他の回答 (10)

回答No.11

ごめん!かんちがい! >li[i] = null; // 要素ノードの参照を外す '}'のいち、みまちがえてました。 onclickをうわがきされると、うごかなくなるよ

think49
質問者

お礼

> onclickをうわがきされると、うごかなくなるよ そうですね。 window.onload と同じく、同じ場所に上書きされると初めに登録したイベントが動かなくなります。 それは承知しているのですが、今回の場合同じ場所にonclickイベントを登録する意義が見あたらないのでいいかなと。 また、「コードはシンプルに」という点には拘ってまして、長いコードは出来るだけ避けたいという思いがあります。 でも、「イベントリスナを使う癖を付けておいた方が良いのでは」という気もしますし、 addEvent() 的な関数を使用して elementNode=null; がいいような気もします。 落としどころが難しく、悩みます…。

think49
質問者

補足

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

回答No.10

たぶん、じぶんもよくりかいできていません。 ところで >li[i] = null; // 要素ノードの参照を外す は、なに? そこまでよんで、なんでいべんといっぱいつけるかなぁ~^^;

think49
質問者

お礼

いろいろとアドバイス有り難うございます。 > そこまでよんで、なんでいべんといっぱいつけるかなぁ~^^; - #3を理解できていない - コードが複雑化するのは避けたい 理解できてない、のが大きいです。 よくわからずに使って弊害が出てしまうのは本末転倒なので…。(苦笑)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.9

そもそも、「保持する」必要ありますか? まぁリソースは有効活用したほうがいいですが・・・ <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>

think49
質問者

お礼

> そもそも、「保持する」必要ありますか? 実際には要素ノードリストを2組持ち、iの値で2つを関連づけています。 関連付けの仕組みを変えればiが不要となるはずですが、アルゴリズムを根本から直す必要がありそうです。 ちなみに、http://vird2002.s8.xrea.com/test/dl2tab.html が実際のスクリプトです。 「同じノードを探し出す」 初めはそのようにしていましたが、そもそも一度捕まえたノードは再利用した方が効率がいいんじゃないか、と思い質問に至りました。 掲示されたコードはアプローチの一つとして参考にさせていただきます。 ありがとうございます。

  • 15mm
  • ベストアンサー率65% (65/100)
回答No.7

前々からできるかどうか不安だった方法を、この際だから調べてみました。 邪道かも。決していい方法であるとは思っていません。 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>

think49
質問者

お礼

> HTMLObjectに勝手にプロパティ追加してます。 こ、こんな方法があるとは…。 FirebugのDOMタブを見ると、「プロパティi」がちゃんと見えています。 IE7でも動きました。動いてしまうんですね…。 ちょっと怖くて使えそうにありませんが、興味深い現象でした。 ありがとうございます。

  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.6

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さんと同じかしら?

think49
質問者

お礼

回答ありがとうございます。 新しくユーザ定義関数を定義したのですね。 もうちょっと簡略化して、 --- 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さんと同じだと思います。 無名関数に引数を渡すためにクロージャを使っていたところが違う部分ですね。

回答No.5

>どのような情報が足りないでしょうか? くろ~じゃ・めもりーりーく・じょうけんつきこんぱいる えらそうなことをいえるほど、おおくをしらないので・・・ ばぶ~!

think49
質問者

お礼

ありがとうございます。 キーワードだけでも参考になります。 質問当初の時点では「メモリーリーク」以外は知りませんでした。 なので、補足要求された情報は持ち合わせていなかったのだと思います。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.4

一例です。 <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/ajaxjs03/ajaxjs03_04.html

think49
質問者

お礼

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

回答No.3

//@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); //ぜんかくくうはくは、てきとうになおしてね ばぶ~! //これだといべんとを、はがしてないよね

think49
質問者

お礼

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

回答No.2

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

think49
質問者

お礼

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

think49
質問者

補足

ひょっとして、#2だけメモリリーク、でしょうか。 - #2でもメモリーリーク (#1,2の両方) - こういうコートがあるけど、メモリーリーク (#2だけ) 見方によって、受け取り方が変わってしまいますね…。

回答No.1

(function(){ var li = document.getElementsByTagName('li'); for(var i=0,max=li.length; i<max; i++){ li[i].onclick = (function(i){ return function() {alert(i);};})(i); } })(); とか

think49
質問者

お礼

なるほど! functionオブジェクトを return したのですね。 私も li[i].onclick = (function(i){ alert(i); })(i); までは思いついたのですが、これでは即実行されてしまってどうしたものかと悩んでいました。 変数を定義しなくていいので非常にいい方法だとは思うのですが、コードが長いのが悩みどころです…。 もっとも、慣れれば気にならなくなるようにも思えるので、大きな問題ではないかもしれません。 ともあれ、解決の糸口が見えてほっとしました。 ありがとうございます。 > 補足要求 どのような情報が足りないでしょうか?

関連するQ&A

  • クリックしたリンクの色を保持して、<object>にそのリンクを表示させる

    下記のプログラムは、クリックしたリンクの色を保持して、<object>にそのリンクを表示させるようになっています。 プログラムの流れは、 (1)test1のリンクをクリックする (2)test1の背景を黄色/文字を太文字に変更 (3)<div id="objarea">にtest1のリンクを表示 (4)次のリンク(test2)がクリックされるまで(2)を保持。クリックされたらtest2のリンクの背景を黄色/文字を太文字に変更。 (5)(1)~(4)の繰り返し。 をすると言う、感じです。ですが、「(3)の<div id="objarea">にtest1のリンクを表示」と言う動作ができなく、リンクの色の保持しか動作しません。 どこがいけないのか分からなくて困っています。どうぞよろしくお願いします。 [サンプルプログラム] <style type="text/css"> <!-- .object { width: 400px; height: 400px; border: 1px solid #000000; } #menu a{ color:#0000ff; text-decoration:none; } #menu .hoge{ color:#ff0000; background-Color:#ffff00; font-weight:bold; } --> </style> <script type="text/javascript"> <!-- function changeObj(url){ document.getElementById('objarea').innerHTML = '<object data="' + url + '" type="text/html"><\/object>'; } //--> </script> <script type="text/javascript"> <!-- window.onload=function(){ setColor(); } function setColor(){ var menu=document.getElementById("menu"); var tags=menu.getElementsByTagName("a"); for (var i=0;i<tags.length;i++){ tags[i].onclick=function(){ var pp=this.parentNode.parentNode; var tags=pp.getElementsByTagName("a"); for (var i=0;i<tags.length;i++){ tags[i].className=""; } this.className="hoge"; } } } if (window.attachEvent){ window.attachEvent('onclick', setColor); window.attachEvent('onclick', changeObj); } else { window.addEventListener('onclick', setColor, false); window.addEventListener('onclick', changeObj, false); } //--> </script> </head> <body> <div id="objarea"> <object data="http://yahoo.co.jp" type="text/html"></object> </div> <ul id="menu"> <li><a href="#" onclick="changeObj('http://yahoo.co.jp'); return false;">test1</a></li> <li><a href="#" onclick="changeObj('http://www.google.co.jp/'); return false;">test2</a></li> </ul> </body> </html>

  • onclickの中のvar i

    天才のプログラマーの皆様に質問です。 要素にonclickイベントを設定したいのですが、下記のコードの問題の行★★★について ご説明をいただけないでしょうか? htmlファイル---------------------------- <input type="button" id="card_0" value="?"> <input type="button" id="card_1" value="?"> <input type="button" id="card_2" value="?"> <input type="button" id="card_3" value="?"> jsファイル------------------------ var el=document.getElementsByTagName("input"); for(var i=0;i<el.length;i++){ console.log(i); // 0,1,2,3 el[i].onclick=function(){ flip(this.id.replace(/^card_/,"")); //関数を設定  正しく設定されている console.log(this.id.replace(/^card_/,"")); // 0,1,2,3 console.log(i); //★★★ 0,1,2,3ではなく、なぜか4が表示されてしまう flip(i)では動作しない flip(this.id.re...略)のthisはel[i]でも動作しません }; } function flip(n){ 略 }

  • チェックの入れ方によってリンク先を変える

    お世話になります。 チェックの入れ方によってリンク先を変える方法ですが、 他の回答者様がすでに回答れていまして、解決しているのですが、質問はチェックボックスが3つという想定ですが、4つあるとして、表記している組み合わせ以外の場合は同じページに飛ばすことはできますでしょうか?元の回答は下記です。わかる方がいたらお願いいたします。 <html> <head> <title>さんぷる</title> <style type="text/css"> #checklist{ list-style-type:none; margin:0;padding:0; } #checklist li{ margin:0;padding:0; } </style> <script type="text/javascript"> function jump1(){ var clist = document.getElementById('checklist').getElementsByTagName('input'); var URLlist = new Array(); URLlist['100'] = '1.html'; URLlist['010'] = '2.html'; URLlist['001'] = '3.html'; URLlist['110'] = '12.html'; URLlist['101'] = '13.html'; URLlist['011'] = '23.html'; URLlist['111'] = '111.html'; var condition=''; for(var i=0;i<clist.length;i++) { condition += (clist[i].checked)?'1':'0'; } if(condition == '000') { alert('チェックが一つもありません'); return; } //alert(URLlist[condition]);return; //テスト用 location.href=URLlist[condition]; } function jump2(){ var clist = document.getElementById('checklist').getElementsByTagName('input'); var condition=''; for(var i=0;i<clist.length;i++) { condition += (clist[i].checked)?i+1:''; } if(condition == '') { alert('チェックが一つもありません'); return; } //alert(condition+'.html');return; //テスト用 location.href=condition+'.html'; } </script> </head> <body> <ul id="checklist"> <li><input type="checkbox" id="cb01"><label for="cb01">項目1</label></li> <li><input type="checkbox" id="cb02"><label for="cb02">項目2</label></li> <li><input type="checkbox" id="cb03"><label for="cb03">項目3</label></li> </ul> <p><input type="button" value="ボタン" onclick="jump1()"></p> </body> </html>

  • active状態のリンクのみを他の画像に置き換える方法

    いつもお世話になっております。 下記のjsの記述で、リンクをクリックするとcssで指定した画像になるようにし、他の範囲内のリンクをクリックしない限りその画像のまま、という状態にしています。(ul id="jmenu"という形で指定しています) 今回は、 <h1>link</h1> <ul id="jmenu"> <li><a href="...">(´・ω・`)</li> </ul> <h1>wonder</h1> <iframe src="..."></iframe> <h1>quest</h1> <ul id="jmenu"> <li><a href="...">(´;ω;`)</li> </ul> という形で、(´・ω・`)をクリックした後、 (´;ω;`)クリックで(´・ω・`)をクリックしている状態を クリアにしたい、と考えているのですが、どのような記述が足りないのでしょうか? 現在ですと、(´・ω・`)がクリアされないため、 (´・ω・`)(´;ω;`)ともにクリックされている状態 (画像が変わっている状態)になってしまっています。 ご教授いただけますと、幸いです。よろしくお願いします。 window.onload=function(){ setColor(); } function setColor(){ var menu=document.getElementById("jmenu"); var tags=menu.getElementsByTagName("a"); for (var i=0;i<tags.length;i++){ tags[i].onclick=function(){ var pp=this.parentNode.parentNode; var tags=pp.getElementsByTagName("a"); for (var i=0;i<tags.length;i++){ tags[i].className=""; } this.className="foge"; } } }

  • javascript バブルソート

    javascriptでバブルソートの実装をしています。 リストにある数値を取得して昇順 or 降順したいのですがうまくいきません。 方法を教えていただけないでしょうか。 よろしくお願いします。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <script type="text/javascript"> function bubbleSort(){ var liVal = document.getElementsByTagName("li"); var array = []; for(var i = 0; i < liVal.length; i++){ for(var j = 0; j < liVal.length-i-1; j++){ array[j] = parseInt(liVal[j].innerHTML); if(array[j] > array[j+1]){ var n = array[j]; array[j] = array[j+1]; array[j+1] = n; } } } } </script> </head> <body> <ul> <li>10</li> <li>5</li> <li>48</li> <li>22</li> <li>679</li> </ul> <p><a href="javascript:void(0);" onclick="bubbleSort()">ソート(降順)</a></p> </body> </html>

  • javascriptとCSSを使ってのドロップダウンメニュー作成

    CSSとJavaScriptを使って ドロップダウンメニューを作ろうと思っているのですが JavaScriptがうまく作動していないためか FireFoxでは表示されるのですが IE6では動きません。 ご教授お願い致します。 ■index.html <head> <script src="javascript/menu.js" type="text/javascript"></script> </head> <div id="nav"> <ul> <li id="category"><a href="~">category</a> <ul> <li><a href="~">Overview</a></li> <li><a href="~">Overview</a></li> </ul> <ul> <li id="category"><a href="~">category</a> <ul> <li><a href="~">Overview</a></li> <li><a href="~">Overview</a></li> </ul> </div> ■menu.js function menuHover() {var menuItems = d.getElementById("nav").getElementsByTagName("li"); for (var i = 0, miL = menuItems.length; i < miL; i++) { menuItems[i].onmouseover = function() { this.className = "mnhover"; } menuItems[i].onmouseout = function() { this.className = ""; } window.onload = menuHover();

  • jQueryでデータを受け渡しで動作が・・・。

    jQueryでデータを受け渡しで動作がどうしてもうまくいきません。 <li>タグにjsonデータを呼び出して表示しています。 それで別の処理のデータを加えるとどうしても最大6行表示の方が機能しなくなってしまいどうしたらうごくのでしょうか? 普通においただけではダメなのでしょうか? <script type="text/javascript"> jQuery(function(){ $.getJSON("./json_sql.php",function(data){ $.each(data,function(i,items){ $("<li/>",{ text : items.category+' '+ items.date+' '+items.content, 'class' : items.category, }).appendTo('ul','#portfolio'); }); }); }); $(document).ready(function() { var max = 6 /* 最大表示数 */ var mx = ':lt(' + max + ')', pf = $('#portfolio li'); pf.filter(':not(' + mx + ')').hide(); $('#navi a').click(function(){ var filterVal = '.' + $(this).text().toLowerCase().replace(' ', '-'); if(filterVal=='.all') filterVal = '*'; pf.filter(':visible').fadeOut('fast', function(){ pf.filter(filterVal + mx).fadeIn('slow'); }); }); }); </script> <div id="main"> <ul id="navi" class="tab"> <li class="all"><a href="#" onclick="document.getElementById('samplebox').style.backgroundColor = '#e2260d';">ALL</a></li> <li class="topix"><a href="#" onclick="document.getElementById('samplebox').style.backgroundColor = '#0f639f';">topix</a></li> <li class="cleaning"><a href="#" onclick="document.getElementById('samplebox').style.backgroundColor = '#0e99b0';">cleaning</a></li> <li class="insurance"><a href="#" onclick="document.getElementById('samplebox').style.backgroundColor = '#0ea653';">insurance</a></li> </ul> <div id="samplebox"></div> <div class="content"> <ul id="portfolio"></ul> </div> <!--/ .main--> </div>

  • Javascriptでプルダウンメニューを作りましたが関数化できません

    <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript"> function foldmenu(i){ var i; for(j=1;j<=5;j++){ if(i==j) $('#sc'+j).toggle('normal'); else $('#sc'+j).hide(); } $(function(i){ $('#c'+i).click(function(){ for(j=1;j<=5;j++){ if(i==j) $('#sc'+j).toggle('normal'); else $('#sc'+j).hide(); } }); }); } </script> <div id="c1" onClick="foldmenu('1')">1</div> <ul id="sc1"> <li><a href="#">入力画面1-1</a></li> <li><a href="#">入力画面1-1</a></li> </ul> <div id="c2" onClick="foldmenu('2')">2</div> <ul id="sc2"> <li><a href="#">入力画面2-1</a></li> <li><a href="#">入力画面2-2</a></li> </ul> <div id="c3" onClick="foldmenu('3')">3</div> <ul id="sc3"> <li><a href="#">入力画面3-1</a></li> <li><a href="#">入力画面3-2</a></li> </ul> <div id="c4" onClick="foldmenu('4')">4</div> <ul id="sc4"> <li><a href="#">入力画面4-1</a></li> <li><a href="#">入力画面4-2</a></li> </ul> <div id="c5" onClick="foldmenu('5')">5</div> <ul id="sc5"> <li><a href="#">入力画面5-1</a></li> <li><a href="#">入力画面5-2</a></li> </ul> と関数化しましたがうまく動きません。 初期状態では1の部分が開く。 それ以降はクリックした部分が開き開いていた部分は閉じるという感じにしたいです。 縦長のプルダウンメニューです。 たてに1から5が並んでいて、1をクリックすると1と2の間に1の子カテゴリーが表示されます。 困っています。教えてください。

  • DOM の 要素の数え方について

    同じクラス名のついた、子要素の数え方を回答いただければと思います。 1. li タグ が 5つあるので、そのような出力にしたいのです。 2. 各 ul の li タグの数を出すには、どのようにすればよいのでしょうか ? どうぞ、皆様よろしくおねがいいたいします。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> <ul class="myClass"> <li>1</li> <li>2</li> </ul> <ul class="myClass"> <li>3</li> <li>4</li> <li>5</li> </ul> <script> try { var chiledNodes = []; function userFunc( parent ) { chiledNodes = document.querySelector( parent ).children; alert ( chiledNodes.length ); } } catch( e ) { alert( e ); } userFunc( '.myClass' ); </script> </body> </html>

  • イベントに適切な値が伝わらない

    0から9までidをもつdivを用意して、それぞれクリックしたら そのidを表示したいのですが、なぜかどれをクリックしても 表示されるのは「10」でした。以下のやり方では何がいけないのでしょうか? function sample(){ for(i=0; i<10; i++){ var obj = document.getElementById(i); obj.onclick = function(){ sample_alert(i); }; } } function sample_alert(i){ alert("i="+i); } window.onload = function() { sample(); } for($i=0; $i<10; $i++){ print "<div id=\"{$i}\">{$i}</div><br>\n"; }