Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从JavaScript调用@JSFunction,TypeError:找不到对象的默认值_Java_Javascript_Rhino - Fatal编程技术网

从JavaScript调用@JSFunction,TypeError:找不到对象的默认值

从JavaScript调用@JSFunction,TypeError:找不到对象的默认值,java,javascript,rhino,Java,Javascript,Rhino,我正在调用@JSFunction带注释的ScriptableObject方法 JavaScript文件 Target = Packages.com.acme.rhino.Target; function evaluate() { var t = Target(); t.addModifier("foobar", 1); return t; } Java文件 public class Target extends ScriptableObject { priva

我正在调用
@JSFunction
带注释的
ScriptableObject方法

JavaScript文件

Target = Packages.com.acme.rhino.Target;

function evaluate() {
    var t = Target();
    t.addModifier("foobar", 1);
    return t;
}
Java文件

public class Target extends ScriptableObject {
    private static final long serialVersionUID = 1L;
    public List<Modifier> modifiers = new LinkedList<>();

    @JSConstructor
    public Target() {
    }

    @JSFunction
    public void addModifier(final String message, final int value) {
        modifiers.add(new Modifier(message, value));
    }

    public int getValue() {
        int sum = 0;
        for (final Modifier modifier : modifiers) {
            sum += modifier.getValue();
        }
        return sum;
    }

    @Override
    public String getClassName() {
        return "Target";
    }
}
不知道从那以后该去哪里。当我不调用
addModifier
方法时,给定的代码可以工作,并且给定堆栈跟踪中的错误
notFunctionError
,我认为Rhino不会将给定的方法解释为JavaScript函数

  • OSX 10.8.2
  • 爪哇7
  • 犀牛1.7R4
可以找到复制错误的完整Maven项目

tl;dr see提出了替代方案

上述方法的问题是
Target.prototype
未在脚本范围内正确设置。有关如何在脚本范围内正确定义原型的详细信息,请参见静态方法

对于为脚本提供
Target
构造函数,您有两种选择。最好是始终为所有脚本定义
目标
构造函数。如果您提前知道希望
Target
在全球范围内可用,那么这种方法很有效。这基本上可以归结为以下几点:

final Context context = Context.enter();
try {
  final ScriptableObject scope = context.initStandardObjects();
  ScriptableObject.defineClass(scope, Target.class, false, true);
  context.evaluateString(scope, script, "script", 1, null);
  // etc.
} finally {
  Context.exit();
}
defineClass("com.acme.rhino.Target");
// whatever `getClassName()` returns is now available
var target = new Target();
如果您希望脚本作者决定哪些构造函数是必需的,则需要为脚本提供
defineClass
函数。使用此函数,脚本作者可以“导入”其类路径上的任何可编写脚本的对象(这可能超出您的允许范围)。要为脚本提供
defineClass
功能,请在输入上下文后执行以下操作:

final Context context = Context.enter();
try {
  final ScriptableObject scope = context.initStandardObjects();
  scope.defineFunctionProperties(
          new String[] {"defineClass"},
          Global.class,
          ScriptableObject.DONTENUM);

  context.evaluateString(scope, script, "script", 1, null);
  // etc.
} finally {
  Context.exit();
}
然后,JavaScript作者利用
Target
构造函数实现以下功能:

final Context context = Context.enter();
try {
  final ScriptableObject scope = context.initStandardObjects();
  ScriptableObject.defineClass(scope, Target.class, false, true);
  context.evaluateString(scope, script, "script", 1, null);
  // etc.
} finally {
  Context.exit();
}
defineClass("com.acme.rhino.Target");
// whatever `getClassName()` returns is now available
var target = new Target();
在上述两个分支中,我做了一些其他更改,如果您向
Target
构造函数添加更多内容,则会使您的设置更好。零参数构造函数不需要
@JSConstructor
注释。如果您以后想要有一个接受参数的构造函数,那么这个零参数构造函数将用作原型构造函数,并且您可以在将用于初始化对象的方法上使用
@JSConstructor
注释。根据您编写此构造函数方法的方式,在JavaScript中使用
new
关键字将变得非常重要

简而言之,
Packages.com.acme…
语法对于从脚本访问
ScriptableObject
构造函数是没有用的。

我通过使用新操作符使它工作(非常类似的代码)。在你的例子中,你在做什么

 function evaluate() {
      var t = new Target();
      ...

也应该可以使用。

请注意,您的github链接不再有效。