【问题标题】:How to create a 'real' JavaScript array in Rhino如何在 Rhino 中创建一个“真正的”JavaScript 数组
【发布时间】:2010-06-22 06:57:44
【问题描述】:

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

我正在尝试调用一个 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

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

【问题讨论】:

  • 您能否在 f() 中添加一些诊断信息,以找出您实际得到的参数是什么?
  • 我添加了一些信息,也许有帮助
  • 图书馆正在做的检查(a instanceof Array)是合理的,但有限。例如,即使没有 Rhino,如果基于浏览器的应用程序中的数组源自另一个窗口,它也将无法识别该数组。您会尝试将result.push(Object.prototype.toString.call(a)); 添加到您的函数中吗?看看它是 [object Object] 还是 [object Array] 会很有趣。后者类似于来自另一个窗口的数组,前者表明NativeArray 并不是名字所暗示的。
  • 您有NativeArray 的JavaDoc 吗?因为这里似乎没有:mozilla.org/rhino/apidocs
  • 在这种特殊情况下,我并不担心任何此类限制,因为我只是在构建过程中尝试运行 JSLint(即,我完全控制了作为参数传递给JSLint) new NativeArray() 等同于调用 Context.newArray() mxr.mozilla.org/mozilla/source/js/rhino/src/org/mozilla/…

标签: javascript arrays rhino


【解决方案1】:

差点忘了: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 构造函数,所以您已经绕过确保其范围正确,因此数组对象的 constructoran Array 构造函数,但不是 相同 Array 构造函数与函数看到的全局对象上的构造函数相同。

【讨论】:

  • 我只是自己想出来的,虽然我可以发誓我今天早些时候尝试过。谢谢!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 2019-07-18
    • 2012-02-19
    • 2019-06-14
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多