首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Rhino Javascript中共享java对象

在Rhino Javascript中共享java对象
EN

Stack Overflow用户
提问于 2012-10-21 23:14:33
回答 3查看 3K关注 0票数 3

首先让我承认我是JavaScript的菜鸟。因此,这个问题在基本情况下可能不是很合理,并且可能缺乏足够的信息来帮助我。

背景

我的组织内部有一个用于JavaScript的基于Eclipse的集成开发环境。我们所要做的就是用JavaScript编写脚本并直接执行它们。我的猜测是它使用Rhino,因为我在一些异常的堆栈跟踪中看到过它。

我的代码运行在3个".js“文件中。

脚本1:声明全局变量并将其实例化为Java对象

代码语言:javascript
复制
importClass(java.util.HashMap);
var hmTCResult = new HashMap();

Script-2:使用Script-1中的全局变量执行一些操作

代码语言:javascript
复制
Script-2.prototype.run = function() {
hmTCResult.put("Result", "Fail");
};

changeStatus = function(strStatus){
hmTCResult.put("Result", strStatus);
};

Script-3:调用Script-2中使用全局变量的函数

代码语言:javascript
复制
changeStatus("Pass") 

问题定义

当我从Script-3调用Script-2中的函数时,似乎没有选择实例变量,我的函数失败了,即我得到了一个异常"hmTCResult not set to the instance of an object“。请注意,相同的变量hmTCResult在脚本1中运行良好。

我已经对JavaScript中的作用域和上下文做了一些阅读,但还没能突破它,因为我在集成开发环境中看不到它。

如果需要的话,我很乐意提供更多的信息。

EN

回答 3

Stack Overflow用户

发布于 2012-11-28 01:59:59

这很好用,只需调整您的范围并设置原型搜索即可:

代码语言:javascript
复制
Context cx = Context.enter();
try {
    // Cache and reuse:
    ScriptableObject sealedSharedScope = cx.initStandardObjects(null,
            true);
    // Force the LiveConnect stuff to be loaded.
    String loadMe = "RegExp; getClass; java; Packages; JavaAdapter;";
    cx.evaluateString(sealedSharedScope, loadMe, "preLoadLazyLoad", 0,
            null);

    cx.evaluateString(sealedSharedScope, "varInRoot = 'blah';",
            "setVarInRoot", 0, null);

    // here you can put more cx.evaluateString calls to set up your
    // environment (eg. hmTCResult)

    // now connect a throw-away new scope into the hierarchy, with local
    // vars:
    Scriptable scope = cx.newObject(sealedSharedScope);
    // ensure that definitions in the root scope are found
    scope.setPrototype(sealedSharedScope);
    // ensure that new global variables are created in this scope (don't
    // use
    // var for them!)
    scope.setParentScope(null);

    cx.evaluateString(scope, "localVar = varInRoot;", "mySource", 0,
            null);
    assertEquals("blah", scope.get("localVar", scope).toString());
    // new var not in root:
    assertEquals(ScriptableObject.NOT_FOUND,
            sealedSharedScope.get("localVar", scope));
} finally {
    Context.exit();
}

注意,scope.get不会搜索原型链--必须自己搜索!

作用域独立于上下文,并且幸存于Context.exit()。

票数 1
EN

Stack Overflow用户

发布于 2012-10-23 05:41:43

要在Java中评估js脚本,可以执行以下操作

代码语言:javascript
复制
ScriptEngine engine = new ScriptEngineManager().getEngineByMimeType( "text/javascript" );
Bindings bindings = engine.getBindings( ScriptContext.GLOBAL_SCOPE );
bindings.put( "varname", ... );
bindings.put( ... );
engine.put( ScriptEngine.FILENAME, script.toString());
engine.eval( new FileReader( script ));

如果这3个脚本是在相同的引擎/绑定中加载的,这是可以的,但如果引擎是新分配来执行script3的,则上下文已被清除。

这篇文章不是真正的答案,但太长了,不能作为评论。

票数 0
EN

Stack Overflow用户

发布于 2012-11-22 06:18:33

我的猜测是,在没有更多信息的情况下,假设您修改后的脚本是绝对正确的,那么您的脚本将在单独的作用域中运行,所有的全局作用域都作为父作用域。

因此,我猜测changeStatus之所以能在第三个脚本中工作,是因为没有对它进行var声明。因此,如果没有其他配置,它将被定义为顶级或全局作用域中的一个变量,该变量在三个脚本之间共享。

我的猜测是,hmTCResult不工作的原因是用关键字var声明的,该关键字表示一个局部变量。如果所有脚本都在顶级作用域中运行,这将在全局对象上定义一个变量。但是如果每个脚本都在自己的作用域中运行,这将只在脚本1的作用域中定义一个变量。您不会在脚本2的作用域中看到这个问题,因为在脚本3执行之前,没有人会执行脚本2中的代码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12999095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档