Проверка особенностей (иногда называемая проверкой функциональных воз' можностей) – это очень мощная методика, позволяющая справиться с пробле_мами совместимости. Особенность, или функциональная возможность, которую вы собираетесь использовать, может поддерживаться не всеми броузерами, по_ этому необходимо включать в свои сценарии программный код, который будет проверять факт поддержки данной особенности. Если требуемая особенность не поддерживается на текущей платформе, тогда можно будет либо не использо_ вать эту особенность на данной платформе, либо разработать альтернативный программный код, одинаково работоспособный на всех платформах.
В следующих главах вы часто будете видеть, что та или иная особенность прове_ ряется снова и снова. Например, в главе 17 приводится программный код, кото_ рый выглядит примерно следующим образом:
if (element.addEventListener) { // Проверить наличие метода W3C перед вызовом element.addEventListener("keydown", handler, false); element.addEventListener("keypress", handler, false);
}
else if (element.attachEvent) { // Проверить наличие метода IE перед вызовом element.attachEvent("onkeydown", handler); element.attachEvent("onkeypress", handler);
}
else { // В противном случае использовать универсальный прием element.onkeydown = element.onkeypress = handler;
}
В главе 20 описывается еще один подход к проверке особенностей: перебирать дос_ тупные альтернативы, пока не будет обнаружена та, которая не генерирует ис_ ключение! А после обнаружения работоспособной альтернативы она запоминается для последующего использования. Вот как выглядит фрагмент из примера 20.1:
// Список функций создания объекта XMLHttpRequest, которые следует опробовать HTTP._factories = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
// Когда обнаружится работоспособный метод, запомнить его здесь
HTTP._factory = null;
276 Глава 13. JavaScript в веб*броузерах
// Создать и вернуть новый объект XMLHttpRequest.
//
// При первом обращении пробовать вызывать функции из списка, пока не будет
// обнаружена та, которая возвращает непустое значение и не генерирует
// исключение. Когда будет обнаружена работоспособная функция, запомнить
// ее для последующего использования.
HTTP.newRequest = function() { /* тело функции опущено */ }
Для проверки версии DOM, поддерживаемой броузером, используется несколь_ ко устаревший способ проверки особенностей, который довольно часто еще мож_ но встретить в существующем программном коде. Обычно его можно встретить в DHTML_коде, и выглядит он примерно так:
if (document.getElementById) { // Если поддерживается W3C DOM API, // исполнить DHTML_код, использующий W3C DOM API
}
else if (document.all) { // Если поддерживается IE 4 API, // исполнить DHTML_код, использующий IE 4 API
}
else if (document.layers) { // Если поддерживается Netscape 4 API,
// исполнить DHTML_эффект (максимум, что нам доступно)
// с использованием Netscape 4 API
}
else { // В противном случае DHTML не поддерживается,
// поэтому следует предоставить статичную альтернативу DHTML
}
Подобный подход считается устаревшим, потому что все современные броузеры поддерживают стандарт W3C DOM и его функцию document.getElementById().
Самое главное, что дает проверка особенностей, – это программный код, который не привязан к конкретным броузерам или их версиям. Этот прием работает со всеми броузерами, существующими ныне, и должен продолжить работать с буду_ щими версиями броузеров независимо от того, какой набор особенностей они реализуют. Однако следует отметить, что при этом производители броузеров не должны определять свойства и методы, не обладающие полной функционально_ стью. Если бы корпорация Microsoft определила метод addEventHandler(), реали_ зовав спецификации W3C лишь частично, это привело бы к нарушениям работо_ способности большого числа сценариев, в которых перед вызовом addEventHand_ ler() реализован механизм проверки особенностей.
Свойство document.all, показанное в следующем примере, заслуживает отдельно_ го упоминания. Массив document.all впервые появился в Microsoft IE 4. Он по_ зволил JavaScript_коду обращаться ко всем элементам документа и стал пред_ вестником новой эры разработки клиентских сценариев. Тем не менее он так и не был стандартизован и был заменен методом document.getElementById(). В на_ стоящее время он по_прежнему встречается в сценариях и часто (хотя и непра_ вильно) служит для того, чтобы выяснить, исполняется сценарий под управле_ нием IE или нет:
if (document.all) {
// Сценарий исполняется в IE
}
else {
13.6. Совместимость на стороне клиента
// Сценарий исполняется в каком_то другом броузере
}
Поскольку до сих пор существует большое число сценариев, использующих свойство document.all, в броузер Firefox была добавлена поддержка этого свойст_ ва, чтобы Firefox мог исполнять те фрагменты программного кода, которые ра_ нее были доступны только для IE. Поскольку присутствие свойства all часто служит для определения типа броузера, Firefox имитирует отсутствие этого свойства. Таким образом, даже при том, что Firefox поддерживает свойство docu_ ment.all, инструкция if в следующем фрагменте сценария ведет себя так, как ес_ ли бы свойство all не существовало, благодаря чему этот сценарий выводит диа_ логовое окно с надписью «Firefox».
if (document.all) alert("IE"); else alert("Firefox");
Данный пример демонстрирует, что механизм проверки особенностей не работа_ ет, если броузер активно сопротивляется этому! Кроме того, этот пример показы_ вает, что веб_разработчики не единственные, кого мучает проблема совместимо_ сти. Производители броузеров также вынуждены идти на всякие хитрости с це_ лью обеспечения совместимости.