7

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

我正在尝试调用一个期望其参数为数组的 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 Array按预期new 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

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

4

2 回答 2

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函数看到的全局对象上的构造函数不同。

于 2010-06-22T09:24:27.137 回答
1

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

于 2013-02-21T14:02:30.237 回答