プロが教える店舗&オフィスのセキュリティ対策術

下記について知っている人が居ましたら教えてください。
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>

A 回答 (4件)

RAMディスク化用のAPPとか常駐Software・Serviceとかによる邪魔の不在証明は、


果たして可能なのでしょうか?
    • good
    • 0

こちらのページが回避策の参考になるかと思います。


http://72.14.235.132/search?q=cache:wS8k0rHFuH4J …
    • good
    • 0

そもそも 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>' );
}
    • good
    • 0
この回答へのお礼

本現象が発生する前に,上記のような連想配列を使用していました。
とても便利な処理方式ですが,
下記のようにArrayが拡張されたものが処理場に存在すると,for inしたときに値が不正になります。
Array.prototype.hogehoge = function() {};
Array.prototype.pagepage = function() {};

あまり納得がいきませんが,
別の処理方式で,意図的に連想配列を作り,メソッド化して地味に対応しました。

お礼日時:2009/06/07 19:17

色々と突っ込み所満載だから全部挙げていくが、まずは本題から。



* 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なんて引っこんで(以下自重
    • good
    • 0
この回答へのお礼

細かいところまで,ご指摘ありがとうございます。
僕も調べたのですが,
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

お礼日時:2009/06/07 16:50

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