首先我要承认我是JavaScript中的菜鸟。所以问题在基础知识上可能不是很合理,可能缺乏足够的信息来帮助我。
我的组织有一个基于Eclipse的内部IDE for IDE。我们所要做的就是用JavaScript编写脚本并直接执行它们。我的猜测是它使用了Rhino,因为我已经在一些例外的堆栈跟踪中看到过它。
我的代码遍历3个“.js”文件。
Script-1:声明全局变量并将它们实例化为Java对象
importClass(java.util.HashMap);
var hmTCResult = new HashMap();
脚本-2:使用Script-1
中的全局变量执行一些操作Script-2.prototype.run = function() {
hmTCResult.put("Result", "Fail");
};
changeStatus = function(strStatus){
hmTCResult.put("Result", strStatus);
};
脚本-3:脚本-2中的调用函数,它使用全局变量
changeStatus("Pass")
当我从Script-3调用Script-2中的函数时,它似乎没有选择实例变量而我的函数失败,即我得到一个异常“hmTCResult未设置为对象的实例。”请注意,相同的变量hmTCResult在脚本1中运行良好。
我已经在JavaScript中完成了对Scope和Context的一些阅读,但是还没有能够突破它,因为我没有在IDE中明确地看到它。
如果需要,我很乐意提供更多信息。
答案 0 :(得分:0)
要在Java中评估js脚本,可以执行以下操作
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,则上下文已被清除。
这篇文章不是一个真正的答案,但是要发表评论的时间太长了。
答案 1 :(得分:0)
我的猜测,如果没有更多信息,并且假设您的修改后的成绩单绝对正确,那么您的脚本将在不同的范围内运行,所有范围都以全局范围作为父级。
因此,我的猜测是changeStatus
在第三个脚本中起作用的原因是因为它没有var
声明。因此,如果没有其他配置,这将被定义为顶级或全局范围内的变量,该变量在三个脚本中共享。
我的猜测是hmTCResult
不工作的原因是它是用关键字var
声明的,表示一个局部变量。如果所有脚本都在顶级作用域中运行,则会在全局对象上定义一个变量。但是如果每个脚本都在自己的范围内运行,那么这只会在脚本1的范围内定义一个变量。你不会在脚本2的范围内看到问题,因为在脚本3之前没有人在脚本2中执行代码执行。
答案 2 :(得分:0)
这很好用,只需要调整范围并设置原型搜索:
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并且存在于Context.exit()。