4

Javascriptには次のコードがあります:

var r=applet.foo({var0:99,var1:'foo',var2:applet});

私のJavaアプレットには、次のものがあります。

public JSObject foo(JSObject args){
    System.out.println("The function is correctly invoked");
    //In fact, the following works perfectly:
    System.out.println("var1 is:"+(String)args.getMember("var1"));
    JSObject w=JSObject.getWindow(this);
    JSObject j=(JSObject)w.eval("new Object();");
    Map m=new Hashmap();

    //TODO here all the keys and values of args should be added to m

    m.put("hello","world");

    //TODO here all the keys and values of m should be added to j

    return j;
}

これはどのように行うことができますか?( TODO )


http://docstore.mik.ua/orelly/web/jscript/ch19_06.htmlを読んで、JSObject の getSlot メソッドがあることに気付きましたが、もしそうなら

args.getSlot(0)

私が持っているのは1つの例外です:

netscape.javascript.JSException: No such slot 0 on JavaScript object
...
4

3 に答える 3

3

残念ながら、Errandir のソリューションは、プロパティの名前を取得したいオブジェクトにアクセスするために使用できるグローバル変数の名前を知っている場合にのみ機能します。keysメソッドをオブジェクトに追加し、後でJSObjectcallメソッドを使用して呼び出すには、この名前を知っている必要があります。もちろん、オブジェクトのグローバル名があれば、それを Java に渡すことができます。このソリューションは、特にグローバル コンテキストでオブジェクトを参照できない場合は、あまり良くありません。

別の方法として、すべての作業を行うと仮定して、コメントでthisofJSObjectevalメソッドを使用することを提案しました。そして、そうです。しかし、大きな失望は、Mozilla Firefox と Opera でしか期待どおりに動作しないことです。Internet Explorer 9 および Google Chrome (Windows 7 および Ubuntu 12.04 LTS でテスト済み) ではthisevalメソッドの は常にアプレットのドキュメント ウィンドウを参照し、どの JavaScript オブジェクトJSObjectインスタンスが実際に表すかを無視します。これがバグなのか、単にLiveConnectがこれらのブラウザーでサポートされていないのか、私にはわかりません。

良いニュースは、callのメソッドがJSObject適切なコンテキストで指定された関数を実行することです。それを念頭に置いて、JavaScript オブジェクトのプロパティの名前のリストを取得する方法を最終的に見つけました。evalアイデアは、メソッドを使用してグローバル コンテキストで一時的な関数を定義することです。この関数は、プロパティを取得したい JavaScript オブジェクトを受け取り、これらのプロパティの名前を配列として返す必要があります。その後、関連する JavaScript オブジェクトの Java 表現を渡すJSObjectのメソッドを介して一時関数を呼び出すことができます (以下のメソッドまたは質問で聞こえるように)。最後に、一時的な機能を削除できます。calljsObjectargs

public static ArrayList<String> getJsObjectPropertiesNames(Applet applet, JSObject jsObject) {

    if (applet == null || jsObject == null)
        return null;

    // Retrieving global context - a JSObject representing a window applet belongs to
    JSObject globalContext;
    try {

        globalContext = JSObject.getWindow(applet);
    }
    catch (JSException ex) {

        return null;
    }

    // Checking whether passed object is not an array
    try {

        jsObject.getSlot(0);
        return null;
    }
    catch (JSException e) {

    }

    String keysFunctionName = String.format("_getKeys%d", Calendar.getInstance().getTimeInMillis());
    jsObject.eval("window['" + keysFunctionName + "'] = function(jsObject) { return Object.keys(jsObject) }");
    JSObject propertiesNamesJsObject = (JSObject)globalContext.call(keysFunctionName, new Object[] { jsObject });
    jsObject.eval("delete(window['" + keysFunctionName + "'])");

    ArrayList<String> propertiesNames = new ArrayList<>();
    try {

        int slotIndex = 0;
        while (true) {

            Object propertyName = propertiesNamesJsObject.getSlot(slotIndex);
            if (propertyName instanceof String)
                propertiesNames.add((String)propertyName);
            slotIndex++;
        }
    }
    catch (JSException e) {

    }

    return propertiesNames;
}
于 2012-12-20T23:33:06.033 に答える
1

解決策として、ここでkeys提案されているようにメソッドを定義できます(を使用して Java コード内で実行できます)。次に、次のようなキーを取得できます。JSObject.eval(...)

JSObject keys = (JSObject)args.call("keys", Collections.EMPTY_LIST);
keys.getSlot(0);
于 2012-10-17T10:21:10.317 に答える
-1

以下に文字列を出力します。必要なものを取得するように変更してください。

public final static String getKeys = "{var keys = [];for (var key in this) {keys.push(key);} keys;}";

private static String printProperties(final Object o,
                                      final boolean printType,
                                      final int level,
                                      final String tab) {
    final StringBuilder sb = new StringBuilder(100);
    if (printType) {
        sb.append("(");
        sb.append(o.getClass().getSimpleName());
        sb.append(") ");
    }
    if (o instanceof JSObject) {
        sb.append("{\n");
        final JSObject js = (JSObject) o;
        final JSObject keys = (JSObject) js.eval(getKeys);
        boolean needComma = false;
        for (int i = 0;; i++) {
            final String key = (String) keys.getSlot(i);
            if ((key != null) && !(key.equals("undefined"))) {
                final Object val = js.getMember(key);
                if (!needComma) {
                    needComma = true;
                } else {
                    sb.append(",\n");
                }
                sb.append(multitab(tab, level));
                sb.append(key);
                sb.append(":");
                sb.append(printProperties(val, printType, level + 1, tab));
            } else {
                break;
            }
        }
        sb.append("\n");
        sb.append(multitab(tab, level - 1));
        sb.append("}");
    } else {
        sb.append(o);
    }
    return sb.toString();
}

private final static String tab = "  ";

private static String multitab(final String tab,
                               int i) {
    final StringBuilder sb = new StringBuilder();
    while (i-- > 0) {
        sb.append(tab);
    }
    return sb.toString();
}
于 2015-08-07T02:13:52.657 に答える