Метод no-argument для window.external вызывается при проверке с помощью typeof
Я пытаюсь отобразить HTML-страницу со встроенным кодом JavaScript внутри элемента управления System.Windows.Forms.WebBrowser
. Ожидается, что код JavaScript будет взаимодействовать со средой внедрения через объект window.external
. Прежде чем вызывать метод на window.external
, JavaScript должен проверить наличие метода. Если его нет, код должен вызывать общий метод резервного копирования.
// basic idea
if (typeof(window.external.MyMethod) != 'undefined') {
window.external.MyMethod(args);
} else {
window.external.Generic("MyMethod", args);
}
Однако проверка метода без аргументов с помощью typeof
, похоже, уже вызывает этот метод. То есть, если MyMethod
принимает любое положительное число аргументов, код выше будет работать отлично; но если MyMethod
- метод без аргументов, то выражение typeof(window.external.MyMethod)
не будет проверять его тип, но также вызывает его.
Есть ли какая-нибудь работа вокруг этого поведения? Можно ли каким-то образом избежать выражения window.external.MyMethod
, чтобы предотвратить вызов метода?
Ответы
Ответ 1
Я не отлаживал вашу точную ситуацию, но я считаю, что мои психические силы могут решить, что здесь происходит.
Язык JScript делает различие между использованием функции и простым упоминанием об этом. Когда вы скажете
x = f;
который говорит: "Назначьте ссылку на функцию, определенную f переменной x". В нем упоминается f. Напротив,
x = f();
использует f. Это означает "вызвать функцию, идентифицированную с помощью f, и присвоить возвращаемое значение x".
Короче говоря, функции в JScript - это то, что мы будем рассматривать как свойства типа делегата в С#.
Некоторые языки не делают этого различия. В VBScript, если вы говорите x = f
, а f - это функция, это значит вызвать функцию, такую же, как x = f()
. VBScript синтаксически не делает сильного различия между использованием и упоминанием функции.
Как все это реализовано, мы используем COM; в частности, мы используем OLE Automation. При отправке поля объекта, чтобы получить его значение, движок JScript передает флаги, которые означают либо "свойство get", либо "invoke метода", в зависимости от того, было ли оно использовано или упоминалось.
Но предположим, что отправляемый объект был написан с ожиданием, что он будет вызван из VB. Возможно, это было написано в VB. Для объекта VB вполне разумно и легально сказать: "О, я вижу, вы спрашиваете меня о значении этого метода. Поскольку я не понимаю разницы между упоминанием метода и его использованием, я просто вызову это независимо от того, какой флаг вы проходите".
Я не знаю, есть ли обходной путь, но я бы поставил столько же, сколько доллар, что то, что происходит, является вызываемым объектом, предполагается, что вызывающий пользователь хочет семантику VB.
Ответ 2
Я нашел это
if ('MyMethod' in window.external)
не вызывает MyMethod
Ответ 3
Попробуйте один из этих
/* Methods for feature testing
* From http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
*/
function isHostMethod(object, property){
var t = typeof object[property];
return t == 'function' ||
(!!(t == 'object' && object[property])) ||
t == 'unknown';
}
function isHostObject(object, property){
return !!(typeof(object[property]) == 'object' && object[property]);
}
if (isHostObject(window.external, "MyMethod")) {....
Ответ 4
Этот эффект можно увидеть в настольном Internet Explorer. A script, например:
for (var i in window) {
console.log('window.' + i + ' = ' + window[i]);
}
завершится с ошибкой, как только будет достигнуто значение external
.
Похоже, что window.external
не является регулярным объектом Javascript, это объект VBScript.
Таким образом, такие выражения, как window.external
и window['external']
, являются операторами VBScript, и, как говорит Эрик L, window.external
в VBScript эквивалентен window.external()
.
Могучий сбивать с толку. Похоже, что это единственный объект, который ведет себя таким образом в Internet Explorer.
Для мобильных браузеров с несколькими браузерами, которые используют IE Mobile window.external.Notify()
для связи с native на Windows Phone 8, но которые также хотели бы установить document.location
на iOS, тестирование на существование window.external.Notify
было бы кажется логичным - но не работает по этой причине.
Я не нашел способа предотвратить это; это все еще происходит при указании type="text/javascript"
в теге script
.
Ответ 5
Таким образом, единственный выбор - это обходные пути:
1) Просто не используйте 0 функций параметров.
2) Сделайте функцию проверки (принимая параметр), чтобы определить, есть ли внешний вызов.
if (typeof(window.external.HasExternal(null)) != 'undefined')
и проверьте, что вместо функции, если внешние функции находятся либо там, либо нет.
3) Для каждой функции без параметров вы хотите либо использовать фиктивный параметр, либо добавить для него 1 функцию проверки параметров, если внешний код меняется в том, какие функции он поддерживает.
Ответ 6
Я действительно не уверен, что это поможет, но попробуйте window.external["MyMethod"]
.
Если это не помогает, попробуйте сохранить это значение в переменной и только затем проверьте тип этой переменной. Посмотрите, поможет ли это.