#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. Я все еще хотел бы, чтобы был лучший способ фактически принудительно выполнить нормализацию, но ваша реализация определенно лучше, чем то, что я делал.