Обработка массива JavaScript — ActiveX против Надстройка FF

#javascript #activex #firefox-addon

#javascript #activex #firefox-дополнение

Вопрос:

Вопрос

Существует ли чистый и надежный способ обработки вызовов плагина, чтобы вызывающий всегда мог ожидать, что ему будет возвращен массив JavaScript, независимо от того, является ли плагин надстройкой Firefox или элементом управления ActiveX? У меня уже есть фактические вызовы плагина, обернутые в функции, такие как:

 function getDevice(deviceKey) {
    return plugin.getDevice(deviceKey);
}
  

Я могу изменить это на что-то вроде:

 function getDevice(deviceKey) {
    return normalizeArray(plugin.getDevice(deviceKey));
}

function normalizeArray(array) {
    return typeof(array) == 'unknown' ? array.toArray() : array;
}
  

но мне все еще нужно помнить, что на самом деле нужно вызывать normalizeArray из функций-оболочек, и кажется, что реализации normalize может не хватать надежности и / или делать некоторые подозрительные предположения.

Есть ли лучший способ справиться с этой ситуацией?

Предыстория

Я пишу некоторый JavaScript для взаимодействия с плагином через JavaScript. Плагин доступен как надстройка в FF и как ActiveX в IE. В плагине доступно несколько методов, возвращающих массивы. В FF вызов:

 typeof(retVal);
  

на объекте возвращает ‘object’. Я могу делать такие вещи, как:

 retVal.length;
retval[0];
  

и они работают так, как ожидалось. Когда я выполняю те же вызовы метода в IE, вызывая:

 typeof(retVal);
  

возвращает ‘unknown’ и вызывает like:

 retVal.length;
retval[0];
  

не определены.

Я провел некоторую отладку и обнаружил, что на самом деле ActiveX возвращает массив вариантов. Этот объект распознается с помощью JScript, а JavaScript-версию массива можно получить, вызвав retVal.toArray() .

Ответ №1:

Я бы сделал нормализацию массива частью оболочки, но сохранил бы ее как отдельную функцию, чтобы:

 function getDevice(deviceKey) {
    return normalizeArray( plugin.getDevice(deviceKey) );
}
  

Вы правы, normalizeArray функция действительно кажется немного хрупкой. Вместо этого вы могли бы захотеть выполнить instanceof тест и даже обернуть его в try ..catch поскольку IE, как известно, делает странные вещи, когда объекты ActiveX тестируются таким образом, поэтому:

 function normalizeArray(obj) {
  try {
    if (obj instanceof Array) {
      return obj;
    }
  } catch(d) {}

  // Convert obj to array - see if toArray property is truthy
  if (obj.toArray) {

    // Is this syntax correct?
    // If it is, call it
    return obj.toArray();

  } else {

    // Not Array, no toArray(), what next?

  }
}
  

Однако я не уверен, является ли объект, возвращаемый вашим плагином Firefox, массивом javascript или он создан в той же области видимости, что и функция normalizeArray (т. Е. Он может быть создан из другого конструктора массива), поэтому тест instanceof завершится неудачей, даже если это массив. Альтернативный тест — это:

 Object.prototype.toString.call(obj) == '[object Array]'
  

который, я думаю, определенно следует включить в try ..catch для IE, если есть хоть какой-то шанс, что obj является объектом ActiveX.

Кстати, typeof — это оператор, нет необходимости использовать оператор группировки ().

Комментарии:

1. Я все еще хотел бы, чтобы был лучший способ фактически принудительно выполнить нормализацию, но ваша реализация определенно лучше, чем то, что я делал.