UWSCでjavascriptのarrayを使う

前に連想配列を検討したときも悩んだんですよね。
UWSCで連想配列を配列にする - じゅんじゅんのきまぐれ
stuncloudさんも微妙に思ったようなので、考えてみた。
UWSCでjson | たっぷす庵



現状の問題

stuncloudさんのスクリプトを流用して問題を提示。

DIM sc = CreateOleObj("ScriptControl")
sc.Language = "JScript"
DIM i, j = sc.Eval("(" + json + ");")

print j.test.a
print LENGTH(j.test.b)	// 2じゃない!
print j.test.b[0]		// エラー!!!


textblock json
{
    "test":{
        "a":"abcde",
        "b":["111111", "222222"]
    }
}
endtextblock

もとのように、Arrayオブジェクトへのアクセスをgetoleitemでやっても良いけど、、、all_ole_itemに入るのが微妙だったりするんですよね。
二重ループできなくなるし。


ということで、解決していきましょう。

LENGTH問題

javascriptのArrayをUWSCのLENGTH関数に渡しても、長さが取れない。
これは簡単。

print j.test.b.length

にするだけ。
これで、期待通り2になります。

要素へのアクセス問題

どうも、[]によるアクセスができないみたいなんですよね。
ということで、対策を考えてみた。
以下は注釈がなければ、

print j.test.b[0]		// エラー!!!

を書き換える想定でお読み下さい。
また、取得側しか書きませんが、設定側も同様です。

関数追加案

sc.AddCode("function Get(o,i) { return o[i]; }")
print sc.Run("Get", j.test.b, 0)

AddCodeを一度やれば、Runで取得できる。
ただ、スマートじゃないですよね。
オブジェクトに対する影響が少ないのがメリット。

対象オブジェクトに関数追加案

これは、textblockも変更する。

print j.test.Get(j.test.b, 0)

textblock json
{
    "test":{
        "a":"abcde",
        "b":["111111", "222222"],
        "Get":function(o,i) { return o[i]; }
    }
}
endtextblock

j.testがくどい、、、。
関数名が文字列でないのが精神衛生上マシな感じ。

対象オブジェクトに専用関数追加案

これも、textblockを変更する。

print j.test.GetB(0)

textblock json
{
    "test":{
        "a":"abcde",
        "b":["111111", "222222"],
        "GetB":function(i) { return this.b[i]; }
    }
}
endtextblock

見栄えはマシになりましたが、Arrayオブジェクトがあるだけ関数を増やす必要があります、、、。

Array変更案

これは、textblockはもとのまま。

sc.ExecuteStatement("Array.prototype.Get = function(i) { return this[i]; }")
print j.test.b.Get(0)

[]でアクセスしたいのはやまやまですが、これが妥協案でしょうか。
ブラウザで実行するようなスクリプトでArrayを直接変更するようなことは、あまりしたくないですが、ま、ScriptControl内のことなので、良いでしょう。
これも、ExecuteStatementは一度やれば全てのArrayが変更されます。


javascriptのオブジェクトはそういうものなのです。