JScript の Array オブジェクトを利用したコード について

解決


IMA  2007-11-25 12:36:26  No: 99813  IP: 192.*.*.*

http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200711/07110042.txt
のスレッドで、魔界の仮面弁士さんのコメントを興味深く拝見しました。

以前から、VB6に無いJavaScriptの配列のsort,push,pop,shift,unshift・・
などの便利なメソッドを使えればなー と考えていました。

>    Set SC = CreateObject("ScriptControl")
>    SC.language = "JScript"
>    SC.ExecuteStatement "List=new Array()"
>    Set List = SC.Eval("List")
>    For n = 1 To 50
>        List.push n
>    Next

上記手法で、利用できるのですね。魔界の仮面弁士さんに感謝いたします。

それで、質問としては
1.単なる配列への読み込みや読み出しを行う場合、処理速度的には
  どうでしょうか?  → 遅くなる、ならない?

2.配列の各中身を取り出すには?
  上の例で、List(n)といった形では取り出せませんでした。
  List.slice(n,n+1) という以外にありませんか?

よろしくお願いします。

編集 削除
魔界の仮面弁士  2007-11-25 14:26:05  No: 99814  IP: 192.*.*.*

> 上記手法で、利用できるのですね。
利用できますが、IDispatchEx の言語実装の差異により、
メンバ名の「大文字小文字が区別される」という問題があります。

たとえば、そのコードで得た Arrray オブジェクトの要素数を調べる際に、
  Debug.Print List.length  'これは OK
  Debug.Print List.Length  'これは NG
という現象が発生します。

Visual Basic では、大文字小文字が自動補正されてしまうため、
この事は、かなり都合が悪いです(VBScript であればまだマシですが)。

自動補正されないよう、「CallByName によるメンバ呼び出し」を検討するか、
「ScriptControl 経由での JScript 呼び出し」にするのが安全かと。


> 1.単なる配列への読み込みや読み出しを行う場合、処理速度的には
>   どうでしょうか?  → 遅くなる、ならない?
VB ネイティブの配列と Long 配列など比べれば遅くはなるでしょうが、それ自体は
単なる COM オブジェクトですから、問題視するほど遅くは無いと思います。
Collection や Dictionary をレイトバインドで使ったときと同程度では無いかと。

まぁ、憶測で答えているだけなので、気になるのであれば、
実際に検証されることをおすすめします。


> 2.配列の各中身を取り出すには?
>  上の例で、List(n)といった形では取り出せませんでした。
JScript 側の変数に対して、スクリプトコントロール経由で
  Debug.Print SC.Eval("List[3]")
のように取り出すことが可能です。

VB 側の変数から取り出す場合は、
  Debug.Print CallByName(List, "3", VbGet)
のように書けます。

ただし範囲外のインデックスが指定された場合、前者のコードでは
Empty が返されるのに対し、後者は実行エラー 438 が発生します。

編集 削除
魔界の仮面弁士  2007-11-25 14:40:48  No: 99815  IP: 192.*.*.*

>>> SC.ExecuteStatement "List=new Array()"
>>> Set List = SC.Eval("List")
これは、
  Set List = SC.Eval("List=new Array()")
の 1 行にまとめられそう。

>> List.slice(n,n+1) という以外にありませんか?
あるいは、「For Each v In List」での取り出しも可能です。

> VB ネイティブの配列と Long 配列など比べれば遅くはなるでしょうが、
う。日本語が変ですね。
「VB ネイティブの Long 配列などと比べれば遅くはなるでしょうが、」
に読み替えてください。


まぁ何にせよ、扱いにくすぎて実用的では無いですね。(^^;
もし使うなら、*.wsc などにカプセル化しておいた方が良いと思います。

編集 削除
IMA  2007-11-25 15:18:01  No: 99816  IP: 192.*.*.*

魔界の仮面弁士さん
詳細な御説明ありがとうございます。

> まぁ何にせよ、扱いにくすぎて実用的では無いですね。(^^;
> もし使うなら、*.wsc などにカプセル化しておいた方が良いと思います。

どの程度使えるか?あるいは扱いにくいか実際に使ってみないと
わからないですね。

> 利用できますが、IDispatchEx の言語実装の差異により、
> メンバ名の「大文字小文字が区別される」という問題があります。

> たとえば、そのコードで得た Arrray オブジェクトの要素数を調べる際に、
>   Debug.Print List.length  'これは OK
>   Debug.Print List.Length  'これは NG
> という現象が発生します。

> Visual Basic では、大文字小文字が自動補正されてしまうため、
> この事は、かなり都合が悪いです(VBScript であればまだマシですが)。

機会があれば使ってみて遊んで見たいと思います。

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

編集 削除
IMA  2007-11-25 15:18:50  No: 99817  IP: 192.*.*.*

解決のチェックを忘れていました。

編集 削除
スクリプトプログラマ  2007-11-25 19:37:29  No: 99818  IP: 192.*.*.*

確認してませんが、
List.3
Eval("List." & n)
とか

編集 削除
スクリプトプログラマ  2007-11-25 19:45:29  No: 99819  IP: 192.*.*.*

JScriptなので、Arrayオブジェクトのプロトタイプにメソッドを追加して、
List.Item(n)
なんて、できますよ。
ただ、そうすると、
For Each x In List
が変なことになって、ちょっと使えなくなります。

編集 削除
スクリプトプログラマ  2007-11-25 19:52:32  No: 99820  IP: 192.*.*.*

sc.AddCode "function Array.prototype.get(i){return this[i];}"
sc.AddCode "function Array.prototype.put(i,v){return this[i]=v;}"
こんなの

編集 削除
IMA  2007-11-26 10:51:04  No: 99821  IP: 192.*.*.*

スクリプトプログラマさん

> sc.AddCode "function Array.prototype.get(i){return this[i];}"
> sc.AddCode "function Array.prototype.put(i,v){return this[i]=v;}"
> こんなの

大変参考になりました。

早速、VBの大文字小文字対応するために
SC.AddCode "function Array.prototype.Length(){return this.length;}"
とやってみました。

しかし、
Debug.Print List.Length  では
function Array.prototype.Length(){return this.length;}
となってしまいます。

Debug.Print List.Length(1) などと適当に引数を与えると
正しく値が得られます。

式を修正することで、引数を与えずに正しいデータを取得する
スクリプトはどの様にすればよいのでしょうか?

よろしくお願いします。

編集 削除
スクリプトプログラマ  2007-11-26 18:24:10  No: 99822  IP: 192.*.*.*

無理でしょう。
CallByName(List,"Length",vbMethod)
Eval("List.Length()")?
それなら最初から
Eval("List.length")
か、
Dim length
ダミー宣言を入れとくとか

あと訂正
List.[3]
Eval("List.[" & n & "]")
ですね

編集 削除
IMA  2007-11-26 20:03:45  No: 99823  IP: 192.*.*.*

> Dim length
> ダミー宣言を入れとくとか

目から鱗です。
そういえば、あのコードを書いたときに・・・
と思い当たりますね!

スクリプトプログラマさん、どうもありがとうございました。

2回目の解決です  (笑

編集 削除