Как создать «настоящий» массив JavaScript в Rhino - PullRequest
7 голосов
/ 22 июня 2010

Хорошо, я немного озадачен.Возможно, мне не хватает чего-то явно очевидного, но, видимо, я просто не вижу леса для деревьев:

Я пытаюсь вызвать функцию 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();

И, увы, result - это false.

Чего мне не хватаетздесь?

Редактировать :
Еще немного информации: и [] 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

Так оно и работает.За исключением того, что я хочу «настоящий» массив:)

Ответы [ 2 ]

8 голосов
/ 22 июня 2010

Почти забыл: 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 голос
/ 21 февраля 2013

Для тех, кто намеренно создает другой подкласс реализации массива и поэтому не может использовать cx.newArray, вы можете сделать следующее: добавить эту строку ScriptRuntime.setBuiltinProtoAndParent(fArgs, scope, TopLevel.Builtins.Array);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...