• 締切済み

prototype.jsを使うとfor~inがバグる件

下記について知っている人が居ましたら教えてください。 HTAでprototype.jsを使うとfor~inでバグります。 具体的に, prototype.jsを読み込んだ状態でfor~inして, for~inの情報を参照すると,値ではなくソースコードが表示されます。 prototype.jsを読み込ませない場合で,通常のようにfor~inして, for~inの情報を参照すると,問題なく値が参照できます。 OS環境とバージョンによって違うかもしれませんが,僕の環境では現象が発生します。 対策方法を知っている人がいましたら教えてください。 下記のソースを実行すると, バグらない場合は,次のように出力されます。 hoge piyo toge バグる場合は,次のように出力されます。 function(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1; } -略- { this._each(function(value) { iterator(value, index++); }); } catch (e) { if (e != $break) throw e; } return this; } hoge piyo toge prototype.js使用すると... ///////////////////////////////////// // sample.hta バグ <html> <head> <title>ツール</title> <script type="text/javascript" src="./prototype.js"></script> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> </body> </html> prototype.js使用しないと... ///////////////////////////////////// // sample.hta バグらない <html> <head> <title>ツール</title> <!-- <script type="text/javascript" src="./prototype.js"></script> --> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> </body> </html> prototype.jsを最後に読み込ませると... ///////////////////////////////////// // sample.hta バグらない <html> <head> <title>ツール</title> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> <script type="text/javascript" src="./prototype.js"></script> </body> </html>

みんなの回答

回答No.4

RAMディスク化用のAPPとか常駐Software・Serviceとかによる邪魔の不在証明は、 果たして可能なのでしょうか?

回答No.3
  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.2

そもそも javascript に連想配列なるものは存在しません。 それから、もともと for in での配列ループは推奨されていないので、配列をループさせたい場合は地道にインデックスで。 配列でなく、オブジェクトを使用すると連想配列のような事も可能です。 var items = {}; item[ 'KEY1' ] = 'hoge'; 又は、 var items = {  KEY1 : 'hoge',  KEY2 : 'piyo',  ... } delete items[ 'KEY1' ]; // items オブジェクトから KEY1 プロパティ削除 for( var key in items ) {  document.write( 'key = ' + key + '<br>' );  document.write( 'value = ' + items[ ket ] + '<br>' ); }

C_se0430
質問者

お礼

本現象が発生する前に,上記のような連想配列を使用していました。 とても便利な処理方式ですが, 下記のようにArrayが拡張されたものが処理場に存在すると,for inしたときに値が不正になります。 Array.prototype.hogehoge = function() {}; Array.prototype.pagepage = function() {}; あまり納得がいきませんが, 別の処理方式で,意図的に連想配列を作り,メソッド化して地味に対応しました。

  • KI401
  • ベストアンサー率53% (44/82)
回答No.1

色々と突っ込み所満載だから全部挙げていくが、まずは本題から。 * Array汚染 全ての原因はprototype.jsがArrayオブジェクトを汚染していることと、 そのArrayコンストラクタを使ってitemやitemsを作っていることだ。 そもそも、この場合のitemやitemsの用途は「ハッシュ(オブジェクト)」であって、配列「ではない」。 だから、初期化式はArrayコンストラクタなど用いず、"var item = {};"と、 ハッシュ(オブジェクト)として初期化すべきだ。 ※以下本題関係なし * language="javascript" <script language="javascript">は「古い記法」だ。 <script type="text/javascript">が推奨される。 * コメントアウト <script>要素内はコメントアウトすべきだ。ブラウザが誤解釈したら困る。 (今時そんなブラウザは皆無だが。) <script type="text/javascript"> //<!-- //--> </script> * コードブロック{ } javascriptにコードブロックの概念はない。よって、スクリプト全体を{}で囲っているが、 全く無意味だ。例えば次のように確かめられる: {var testvar = 1;} alert(testvar); // -> 1 ... NOT local variable!! 同じ理由で、for文の初期化式でindex用の変数i,jを宣言するのは好ましくない。次のように書くべき: var i; for (i=0; i<n; i++) {} * new Hoge() そもそも、使わなくていいならnew演算子はあまり使わない方がいい。 "new Array()"の代わりに[]を、"new Object()"の代わりには{}を使えばいい。 * prototype.js そもそもそもそも、こんな汚染を引き起こしやがるprototypeなんて引っこんで(以下自重

C_se0430
質問者

お礼

細かいところまで,ご指摘ありがとうございます。 僕も調べたのですが, Array汚染がされているみたいですね。 別の処理方式で検討してみます。 <script type="text/javascript"> //<!-- {   Array.prototype.hogehoge = function() {};  // <-- 原因   Array.prototype.pagepage = function() {};  // <-- 原因   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } //--> </script> 結果: function() {} function() {} hoge piyo toge

関連するQ&A

  • prototype宣言によるメソッドと、プロパティを区別

    Array.prototype.myInclude = function(){ } というように配列にメソッドを追加しました。この上で hoge = new Array(); hoge["mikan"] = "orange"; hoge["ringo"] = "red"; for( var i in hoge ){ alert( i ); } とすると、 myInclude orange red と始めに追加したメソッドまで拾ってしまいます。 既にいくつかprototypeで書いてしまいました。 for~inの部分の書き換えでできる方法は無いでしょうか。

  • js プロトタイプ

    javascriptソースコード <!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" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>サンプル</title> </head> <body> <script type="text/javascript" src="jquery-1.7.2.min.js"></script> <script src="fastclick.js"></script> <script> function print(str){ document.write(str + "<br />"); } function Car(manufact, name){ this.manufact = manufact; this.name = name; } Car.prototype.info = function(){return this.manufact + " " + this.name;}; document.write("<p>"); var car1 = new Car("Toyota", "PRIUS"); print(car1.info()); var car2 = new Car("Honda", "INSIGHT"); print(car2.info()); document.write("</p>"); </script> </body> </html> 23行目なのですが「 Car.prototype.info 」とありますがjsにおいてプロトタイプはオブジェクトだという事は認識しておりますがプロトタイプを宣言する意味は何があるのでしょうか? 参考urlです。 http://www.ajaxtower.jp/js/function_class/index3.html

  • 呼出したjsファイル内で他jsファイルを呼出したい

    hoge.htmlに ----------------------------------------------- <script type="text/javascript" src="piyo.js"></script> ----------------------------------------------- を記述してpiyo.jsを読み込ませました。 この状況で、piyo.js内でfuga.jsを読み込むにはどのような記述をすればよいでしょうか?

  • prototype.jsを利用したイベントの登録について

    はじめまして。 現在 prototype.js 1.4.0 を利用して、Web ページの作成を行っているのですが、イベントの登録 (Event.observe)でやりたいことと、異なる動作になってしまい困っているところです。 [ やりたいこと ] javascript側で動的に生成した各要素 (div) に対して moueover & mouseout のイベントを割り当てる。mouseover 時には background の値を変え mouseout 時には background の値を元(transparent)に戻す。 [ 困っていること ] 各要素のmouseover & mouseout 時には各要素の背景色が変更されるはずなのに、一番最後に生成した要素の背景が変更されてしまう。 [ コード ] <html> <head> <script type="text/javascript" src="prototype.js" ></script> <script type="text/javascript"> view = new Class.create(); view.prototype = { initialize:function() { var view = $('viewContents'); var idName = 'test'; for (var i=0; i<10; i++) { var id = idName + i; var d = document.createElement('div'); d.id = id; d.innerHTML = id; view.appendChild(d); Event.observe(d,'mouseover',function() {d.style.background='#aaa';}.bind(this),false); Event.observe(d,'mouseout' ,function() {d.style.background='transparent';}.bind(this),false); Event.observe(d,'click' ,function() {alert(d.id);}.bind(this),false); } } } </script> </head> <body> <p><input type="button" onclick="new view();" value="取得"></p> <div id="viewContents"></div> </body> </html> となります。 なにか基本的なところが間違っているのでしょうか? よろしくお願いいたします。

  • prototype.jsを利用して

    よろしくお願いします。prototype.jsを使い、 データバインドを利用せず、csvファイルを読込ませ、safariで 表示できるようにサンプルを利用して作成しました。 csvのレコードは400くらいあります。このレコードデータを テーブル3列の繰り返しで表示したいのですが、以下のソースで 行うようにするとどうしても3列表示したら繰り返しせず 終了してしまいます。 3列表示させる部分の値を変数へ渡してループにすれば出来るような感じがするのですが、そのように想定したものを記述してもどうしても 3列で終了してしまいます。 データバインドで散々質問したのですが、再度お知恵をお借りしたいです。どうかよろしくお願いします。 --------------------------------------------------------------- <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript"> <!-- window.onload = function(){ var msec = (new Date()).getTime(); new Ajax.Request("list2.csv", { method: "get", parameters: "cache="+msec, onSuccess:function(httpObj){ var text = httpObj.responseText; var LF = String.fromCharCode(10); var tabText = text.split(LF); var color= "red"; var leng=tabText.length; var retu=0; var cnt=0; var m=0; var tbl = "<table border='1'>"; var tbb = "<td><table border='1'>"; while(cnt<3){ //試しに3回ループさせてみる tbl += "<tr>"; var w=m; var a=w; var s=w+1; var f=0; while(retu<3){ //3列分表示 tbl += "<td><table border='1'>"; for (var i=a; i<s; i++){  var cText = tabText[i].split(","); tbl += "<tr><td><img src="+cText[0]+"></td></tr>"; tbl += "<tr><td>"+cText[1]+"</td></tr>"; tbl += "<tr><td>"+cText[2]+"</td></tr>"; tbl += "<tr><td>"+cText[3]+"</td></tr>"; tbl += "<tr><td>"+cText[4]+"</td></tr>"; tbl += "<tr><td>"+cText[5]+"</td></tr>"; } a=a+1; s=s+1; retu++; tbl += "</table></td>"; } tbl += "</tr></table>"; cnt++; m=m+3; } $("tableData").innerHTML = tbl+color+leng+a; //変数で表示させたいものをここで宣言 }, onFailure:function(httpObj){ $("tableData").innerHTML = "エラーで読み込めませんでした"; } }); } //--> </script>

  • コンストラクタとプロトタイプについて

    ネットで検索したりして調べているのですがいまいちわからなかった箇所が あるので質問させていただきます。 コンストラクタで設定するのとプロトタイプで設定する違いがいまいちわかりません。 例えば function Test { this.prop = hoge; } Test.prototype.prop1 = hogehoge; の場合 コンストラクタのほうが優先されてhogeがでるのはわかるのですが 下記の場合はプロタイプのほうが優先されてhogehogeと出てしまうのは どうしてでしょうか? <script language="javascript"> <!-- //コンストラクタ function Test(){alert("hoge"); } //prototypeでセット Test.prototype=alert("hogehoge"); //オブジェクト作成 var TEST = new Test(); window.onload=TEST; --> </script>

  • js array -1

    javascriptのソースコードの引用なのですが <!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" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>サンプル</title> </head> <body> <script type="text/javascript" src="jquery-1.7.2.min.js"></script> <script src="fastclick.js"></script> <script> function print(str){ document.write(str + "<br />"); } document.write("<p>"); var ary = new Array("東京", "大阪", "名古屋"); for (var i = 0 ; i < ary.length ; i++){ print("array[" + i + "] = " + ary[i]); } document.write("</p>"); document.write("<p>"); try{ var ary2 = new Array(-1); }catch(e){ print(e); } document.write("</p>");</script> </body> </html> 30行目try文の中の「 var ary2 = new Array(-1); 」なのですがnewで初期化をしているという事は何となく理解できるのですが 引数で-1を指定しているのですが-1を指定する意味は何かあるのでしょうか?

  • prototype の使い方

    prototype プロパティについて勉強しているのですが、次のような使い方で正しいのでしょうか。 var Dog = function() { this.sit = "I am sitting."; } var myDog = new Dog(); alert(myDog.sit); //“I am sitting.”と表示される。 var Dog2 = function() {} Dog2.prototype.sit = new Dog().sit; var myDog2 = new Dog2(); alert(myDog2.sit); //“I am sitting.”と表示される。 prototype の行で new Dog() を作るとゴミが出る気がするのですが、勝手に解放されるのでしょうか。

  • Array.prototype は使用しない方がいい?

    prototypeの有名な問題にobjentオブジェクト汚染、Arrayオブジェクト汚染があると思います。 - 現在ブラウザに実装されているJavaScriptにはforEachがない - forEachの代替としてfor~inが使われている - for~in はオブジェクトのプロパティを列挙する - forEachの代替としてfor~inが使われる事を考慮して、object.prototype は使用すべきではない Object オブジェクトの prototype に便利メソッドを放り込むのはやめて頂きたい - nazonoDiary http://d.hatena.ne.jp/nazoking/20050425/1114374966 for...in - MDC https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Statements/for...in この理屈はわかります。 一方、Array.prototype はなぜ使用してはいけないのでしょうか? ---- // 数値添字配列 Array.prototype.test=function(){ return 'test'; }; var arr = [1,3,5,7,9]; for(var i=0,l=arr.length; i<l; i++){ console.info(arr[i]); // コンソール出力(要Firebug) } // オブジェクト (連想配列ではない) Array.prototype.test=function(){ return 'test'; }; var arr = { a:1,b:3,c:5,d:7,e:9 }; for(var i in test){ console.info(test[i]); // コンソール出力(要Firebug) } ---- どちらも問題なく動作します。 問題が発生するとすれば「数値添字配列でfor~inを使用するケース」ですが、それは実装が誤っていると思います。 for~inはオブジェクトのプロパティを列挙する仕組みなので、prototypeで拡張したプロパティまで列挙されるのは自然な動作です。 私はこれを「for~inバグ」と呼ばれることに違和感を覚えるのですが…。 「数値添字配列でfor~inを使用するライブラリがとても多いから、Array.prototype は止めよう」ということなのでしょうか? JavaScript の Array オブジェクトを汚染させずに拡張してみる - Cyokodog::Diary http://d.hatena.ne.jp/cyokodog/20081031/ArrayExtend01

  • prototype.js で $ is not defined になってしまう!

    JSバージョン:prototype1.6 ブラウザ:Firefox2.0、IE7.0 OS:WinXPpro でシンプルに <html> <head> <title>$ - 指定idのエレメントを取得</title> </head> <script type="text/javascript" src="/js/prototype.js?aaads"></script> <script type="text/javascript"> function test1() { var element = $('div1'); alert(element.innerHTML); } </script> <body> <div id="div1">DIV1の中身</div> </body> </html> を実行したところ、$ is not defined と エラーになってしまいます。 あるレンタルサーバにUPして動かすと問題なく、 ローカルPCで実行するとエラーになってしまうようです。 どなたか教えて下さい!!!

専門家に質問してみよう