java-在Rhino中返回主机对象

在Rhino中将宿主对象返回JavaScript的最佳方法是什么?我有两个这样的课程:

public class Hosted extends org.mozilla.javascript.ScriptableObject {
    private static final long serialVersionUID = 1;
    public Hosted() {}
    public void jsConstructor() {}

    public String getClassName() {
        return "Hosted";
    }

    public Member jsGet_member() {
        Member m = new Member();
        m.defineFunctionProperties(new String[] { "toString" }, m.getClass(), DONTENUM);
        return m;
    }
}

public class Member extends org.mozilla.javascript.ScriptableObject {
    private static final long serialVersionUID = 2;
    public Member() {}
    public void jsConstructor() {}

    public String getClassName() {
        return "Member";
    }

    public String toString() {
        return "called toString()";
    }
}

从我可以调用toString方法的意义上讲,它是有效的,但是成员对象的行为不符合我的预期:

js> defineClass("Hosted");
js> defineClass("Member");
js> var h = new Hosted();
js> h.toString();
[object Hosted]
js> h instanceof Hosted;
true
js> h.__proto__;
[object Hosted]
js> 
js> var m = h.member;
js> m.toString();
called toString()
js> m instanceof Member; // Should be true
false
js> m.__proto__; // Should be [object Member]
null

如果我调用Object.prototype.toString,它会说这是一个Member对象:

js> Object.prototype.toString.call(m);
[object Member]

我试过调用m.setPrototype和Context.javaToJS.

解决方法:

    public Scriptable jsGet_member() {
        Scriptable scope = ScriptableObject.getTopLevelScope(this);
        Member m = new Member();
        m.setParentScope(scope);
        // defineClass("Member") must have previously been called.
        m.setPrototype(ScriptableObject.getClassPrototype(scope, "Member"));
        m.defineFunctionProperties(new String[] { "toString" },
                m.getClass(), DONTENUM);
        return m;
    }
js> defineClass("Member")
js> defineClass("Hosted")
js> var h = new Hosted();
js> var m = h.member;
js> m.toString();
called toString()
js> m instanceof Member;
true
js> m.__proto__;
[object Member]

编辑:该方法也可以编写为:

    public Scriptable jsGet_member() {
        Scriptable scope = ScriptableObject.getTopLevelScope(this);
        Context cx = Context.getCurrentContext();
        Member m = (Member)cx.newObject(scope, "Member");
        m.defineFunctionProperties(new String[] { "toString" },
                m.getClass(), DONTENUM);
        return m;
    }

它将调用Member.jsConstructor;可能还有其他差异.

上一篇:javascript-如何在json对象中使用可变定义的键?


下一篇:从对象内调用时,使用’eval’定义*函数时遇到麻烦