Javascript instanceof & typeof в GWT (JSNI) - PullRequest
3 голосов
/ 31 мая 2010

Я столкнулся с любопытной проблемой при попытке использовать некоторые объекты через JSNI в GWT. Допустим, у нас есть файл javscript с определенной функцией:

test.js:

function test(arg){
  var type = typeof(arg);
  if (arg instanceof Array)
    alert('Array');
  if (arg instanceof Object)
    alert('Object');
  if (arg instanceof String)
    alert('String');
}

И мы хотим вызвать эту функцию пользователем JSNI:

public static native void testx()/ *-{
  $wnd.test( new Array(1, 2, 3) );
  $wnd.test( [ 1, 2, 3 ] );
  $wnd.test( {val:1} );
  $wnd.test( new String("Some text") );
}-*/;

Вопросы:

  • почему instanceof инструкции всегда будут возвращать false?
  • почему typeof всегда будет возвращаться "object"?
  • как передать эти объекты, чтобы они были правильно распознаны?

Ответы [ 3 ]

7 голосов
/ 31 мая 2010

instanceof не должен возвращать false все время в вашем примере , если вы не тестируете объекты из другого окна, потому что массив из одного окна не экземпляр Array конструктора другого окна.

Использование instanceof замечательно, когда вам нужно проверить какую-то конкретную вещь, и вы работаете в одном окне (вы должны знать о строковом примитиве и объекте String, о котором говорил Скунлифф). Обратите внимание, что вы должны быть осторожны с вашим порядком, так как массив является instanceof Object (а также Array); это относится и к String s, и ко всем другим объектам.

Существует альтернатива, в которой нет проблемы с окном, и которую можно легко использовать для операторов switch и т. П., Если вы выполняете диспетчеризацию:

function classify(arg) {
    return Object.prototype.toString.call(arg);
}

Это выглядит странно, но для этого используется функция toString на прототипе Object, которая имеет определенное поведение (вместо использования любого переопределения, которое может иметь реальный объект, который вы тестируете, который может иметь другое поведение). Итак, учитывая эту функцию:

function show(arg) {
    alert(classify(arg));
}

вы получите эти результаты:

show({});               // [object Object]
show("a");              // [object String]
show(new String("a"));  // [object String]
show([]);               // [object Array]
show(/n/);              // [object RegExp]
show(function() { });   // [object Function]

и вы получите эти результаты независимо от того, из какого окна поступает объект, который вы тестируете, и независимо от того, используете ли вы строковый примитив или экземпляр String.

1 голос
/ 01 июня 2010

Поскольку на все остальное, похоже, ответили, позвольте мне получить это:

как передать эти объекты, чтобы они были правильно распознаны?

GWT делает это автоматически для примитивных типов, таких как строки, целые числа и т. Д. Таким образом, вы можете написать просто:

public static native String test1()/ *-{
   return "adfasdf";
}-*/;

public static native int test2()/ *-{
   return 23;
}-*/;

См. документы для некоторых дополнительных заметок.

Для массивов существует несколько классов-оболочек: JsArray, JsArrayBoolean, JsArrayInteger, JsArrayNumber , JsArrayString.

public static native JsArrayString test3()/ *-{
   return ['foo', 'bar', 'baz'];
}-*/;
0 голосов
/ 31 мая 2010

ваша тестовая функция всегда возвращает false, потому что вы не предоставляете оператор возврата ... и String забавно в JavaScript ... если вы используете new String("asdf");, тогда использование instanceof будет работать, если вы просто создадите строку с "asdf" тогда вам нужно будет использовать typeof.

function test(arg){
  if (arg instanceof Array){
    return 'Array';
  } else if(arg instanceof String || typeof(arg) == 'String'){
    return 'String';
  } else if (arg instanceof Object){
    return 'Object';
  } else {
    return typeof(arg);
  }
}

(обратите внимание, что существуют другие типы ... Дата, Число, Пользовательские объекты и т. Д.)

...