Определение версии Internet Explorer (IE) в JavaScript

Краткое описание
Определение версии браузера Internet Explorer (IE) средствами JavaScript, безопасное для применения совместно с минимизацией (minification).

Необходимые условия

Чтобы описанный в статье способ гарантированно работал, необходимо следующее:

  • HTML-документ должен работать в режиме соответствия стандартам, для чего нужно правильное объявление DOCTYPE.
  • В Internet Explorer должен быть выключен режим эмуляции устаревших версий IE. Пере­ключение в режим эмуляции можно запретить с помощью мета­элемента или HTTP-заголовка ответа сервера X-UA-Compatible.

Оба условия в любом случае необходимы для правильной и предсказуемой работы любой веб-страницы даже безотно­сительно определения версии IE в JavaScript.

Описание

Отличить Internet Explorer версий 10 и ниже от других браузеров в JavaScript-сценариях можно путём проверки булевой истинности нестан­дартного объекта document.all, из рас­прост­ранённых браузеров доступного только в IE10 и ниже. Проверять необходимо не существование объекта, а именно его булеву истинность, т. к. для совместимости с IE сам объект поддерживается и в других браузерах.

Определить конкретную версию IE можно путём дополни­тельной проверки сущест­вования глобальных объектов, появившихся только начиная с опре­делённой версии IE.

В IE11 есть специфичный для IE нестан­дартный объект window.msCrypto. IE11 — последняя версия IE, после которой разработку IE прекратили, поэтому сущест­вование window.msCrypto одно­значно иденти­фицирует IE11.

В таблице ниже приведены объекты-индикаторы для разных версий IE.

Версии IE Поддерживаемый объект
11 window.msCrypto
10+ window.atob
9+ document.addEventListener
8+ document.querySelector
7+ window.XMLHttpRequest
6+ document.compatMode

Проверяя сущест­вование этих объектов и при необходимости сочетая такие проверки, можно достоверно фильтровать конкретную версию или диапазон версий IE.

Метод надёжно работает в том числе при применении совместно с мини­мизацией (minification) кода.

В следующей таблице приведены готовые условия.

Версии IE Условие для проверки
11 и ниже document.all || window.msCrypto
10 и ниже document.all
9 и ниже document.all && !window.atob
8 и ниже document.all && !document.addEventListener
7 и ниже document.all && !document.querySelector
6 и ниже document.all && !window.XMLHttpRequest
5.x document.all && !document.compatMode

Примеры

Следующее условие выполняется только в IE версии 7 и ниже:

if (document.all && !document.querySelector) {
    alert('IE7 или ниже');
}

Следующее — в IE8, но не в IE7 или IE9+:

if (document.all && document.querySelector && !document.addEventListener) {
    alert('IE8');
}

Условие в следующем примере истинно в том случае, если браузер — IE11+ или не IE:

if (!document.all) {
    alert('IE11+ или не IE');
}

А так можно обнаружить конкретно IE11:

if (window.msCrypto) {
    alert('IE11');
}

Применение в behavior (*.htc)

HTML Components (файлы *.htc) — особые HTML-документы, содержащие JavaScript-сценарии, привязываемые к HTML-элементам при помощи нестан­дартного CSS-свойства behavior, поддер­живаемого только в IE. Для определения версии IE с исполь­зованием проверки сущест­вования объектов htc-файл должен быть снабжён DOCTYPE-объявлением подобно любому корректному HTML-документу:

<!DOCTYPE html>

В противном случае почти все пере­численные выше объекты-признаки (кроме window.XMLHttpRequest) будут отсут­ствовать вне зави­симости от версии IE.

Кроме того, поскольку behavior поддер­живаются только в IE, проверка сущест­вования document.all в этом случае не нужна.

Определение версии браузера и хорошие практики

В общем случае наличие функцио­нальности следует проверять напрямую. Например, чтобы узнать, доступен ли JavaScript-метод querySelector(), следует проверить сущест­вование именно объекта querySelector. В противном случае возможны ситуации, когда скрипт будет считать возможность недоступной, хотя реально она доступна, и наоборот.

Однако зачастую IE является единственным браузером, где недоступна определённая функцио­нальность, поэтому проводить в других браузерах формально «полно­ценные», но медленные проверки может быть нецеле­сообразным.

Например, чтобы проверить, поддер­живает ли браузер CSS-свойство display: table, формально следует поступить так:

  1. создать временный элемент;
  2. присвоить его свойству style.display значение table;
  3. сравнить значение style.display с table.

Но учитывая, что display: table давно поддерживается всеми отличными от IE браузерами, а в IE поддержка была реализована начиная с 8-й версии, достаточно просто проверить версию IE по косвенному признаку:

if (document.all && !document.querySelector) { // IE7 или ниже
    alert('{display: table} не поддерживается');
}

Такая проверка отработает намного быстрее и при этом вполне безопасна для будущих версий браузеров.

Другие способы определения версии IE

Условная компиляция (conditional compilation)

Внимание
Начиная с IE11, условная компиляция более недоступна.

Иногда для определения версии IE используются директивы условной компиляции — нестандартные условные конструкции, поддер­живаемые только в IE и обычно заключаемые в комментарии JavaScript, чтобы гарантировать формальную синтак­сическую корректность кода и, следова­тельно, совме­стимость с другими браузерами.

Определение версии IE в этом случае основано на одно­значном соответ­ствии версий IE и движка JavaScript, исполь­зуемого в конкретной версии IE:

Версия IE 10 9 8 7 6
Версия движка JavaScript 10 9 5.8 5.7 5.6

Например, следующий код можно исполь­зовать для определения версий IE с 3-й по 10-ю:

var ieVersion = /*@cc_on (function() {switch(@_jscript_version) {case 1.0: return 3; case 3.0: return 4; case 5.0: return 5; case 5.1: return 5; case 5.5: return 5.5; case 5.6: return 6; case 5.7: return 7; case 5.8: return 8; case 9: return 9; case 10: return 10;}})() || @*/ 0;

К сожалению, условная компиляция небезопасна при исполь­зовании в сочетании с мини­мизацией JavaScript-кода (например, при помощи Google Closure Compiler), поскольку соответ­ствующими алгоритмами комментарии обычно удаляются.

Кроме того, исполь­зование условной компиляции для определения версии IE работает корректно только в настоящих версиях IE. В режимах эмуляции предыдущих версий IE (такая возможность доступна в IE8 и выше в панели, вызываемой по нажатию клавиши F12) служебная константа @_jscript_version содержит номер версии JavaScript-движка реальной версии IE вне завимости от того, находится он в режиме эмуляции старой версии IE или нет. Это потенциально затрудняет отладку JavaScript-сценариев для работы в разных версиях IE. В IE11 условная компиляция доступна только в режиме совме­стимости с IE10 и ниже.

Свойство document.documentMode

Более удобным и предсказуемым, чем условная компиляция, является использование нестандартного свойства document.documentMode, содержащего номер версии IE с учётом режима эмуляции одной из предыдущих версий IE, если таковой включён:

if (document.all && document.documentMode && 8 === document.documentMode) {
    alert('IE8 или IE9+ в режиме совместимости с IE8');
}

Свойство document.documentMode доступно только в IE8 и выше, поэтому различение версий IE ниже 8 с помощью этого свойства невозможно. Для определения диапазона версий ниже 8 требуется более сложное условие:

if (document.all && (!document.documentMode || (document.documentMode && document.documentMode < 8))) {
    alert('IE7 или ниже или IE8+ в режиме совместимости с IE7');
}

Условные комментарии (conditional comments)

Внимание
Начиная с версии 10, поддержка условных комментариев в Internet Explorer прекращена.

Условные комментарии — нестан­дартная возможность, доступная только в IE9 и ниже и основанная на комментариях HTML.

Для определения версии IE в JavaScript условные HTML-комментарии можно задей­ствовать по-разному.

  • Инициализация JavaScript-переменных непосред­ственно в статическом HTML-коде:

    в HTML-файле:
    <script>
        var ie = false;
    </script>
    <!--[if lte IE 7]><script>
        ie = 7;
    </script><![endif]-->
    в JavaScript-файле:
    if (7 === ie) {
        alert('IE7 или ниже');
    }

    Исполь­зование условных комментариев в статическом HTML-коде страдает недостаточной гибкостью, приводит к заму­сориванию HTML-кода и распылению логики на несколько файлов, затрудняя работу с таким кодом.

  • Динамическая генерация временного HTML-элемента, содержащего узел, заключённый в условный комментарий, и последующая проверка, был ли условный комментарий обработан браузером (если условие в условном комментарии истинно, IE авто­матически заменяет в DOM-дереве условный комментарий его содержимым):

    var test = document.createElement('div');
    test.innerHTML = '<!--[if lte IE 7]>1<![endif]-->';

    if ('1' === test.innerHTML) {
        alert('IE7 или ниже');
    }

    По сравнению с проверкой сущест­вования глобальных объектов этот метод менее изящен и может работать медленнее.