如何在Rhino中创建一个“真正的”JavaScript数组

时间:2010-06-22 06:57:44

标签: javascript arrays rhino

好的,我有点难过。我可能错过了一些明显的东西,但显然我只是看不到森林中的树木:

我正在尝试调用一个JavaScript函数,它希望它的参数是一个数组,即它检查if (arg instanceof Array)...不幸的是,我(或Rhino)似乎无法创建这样的数组:

  Context cx = Context.enter();
  Scriptable scope = cx.initStandardObjects();
  String src = "function f(a) { return a instanceof Array; };";

  cx.evaluateString(scope, src, "<src>", 0, null);

  Function f = (Function) scope.get("f", scope);
  Object[] fArgs = new Object[]{ new NativeArray(0) };
  Object result = f.call(cx, scope, scope, fArgs);

  System.out.println(Context.toString(result));

  Context.exit();

唉,resultfalse

我在这里缺少什么?

修改
更多信息:[] instanceof Arraynew Array() instanceof Array返回true正如人们所期望的那样。如果我向数组添加元素,它们会在JavaScript代码中显示正确的索引(数字,从零开始):

  NativeArray a = new NativeArray(new Object[]{ 42, "foo" });

使用此JavaScript函数输出时:

  function f(a) {
      var result = [];
      result.push(typeof a);
      for (var i in a) {
          result.push(i + ' => ' + a[i]);
      }
      return result.join('\\n');
  }

结果是:

  object
  0 => 42
  1 => foo

所以它有效。除了我想要一个'真正的'数组:)

2 个答案:

答案 0 :(得分:8)

  

几乎忘了:Object.prototype.toString.call(a)返回[object Array]

好的,这是至关重要的信息。这告诉我们数组实际上是一个数组,它只是由一个Array构造函数初始化,其范围与函数测试的范围不同,就像从一个窗口测试一个数组一样在基于浏览器的应用程序中针对另一个窗口的Array构造函数。例如,存在范围问题。

尝试替换

Object[] fArgs = new Object[]{ new NativeArray(0) };

Object[] fArgs = new Object[]{ cx.newArray(scope, 0) };

...确保使用正确的Array构造函数。因为您已经直接转到NativeArray构造函数,所以您绕过了确保其范围正确,因此数组对象的constructor Array构造函数,但不是与函数看到的全局对象上的相同的 Array构造函数。

答案 1 :(得分:1)

对于那些故意创建数组实现的不同子类的人,因此不能使用cx.newArray,你可以做的是: 添加此行 ScriptRuntime.setBuiltinProtoAndParent(fArgs, scope, TopLevel.Builtins.Array);