JavaScript. Интересный факт об определении типа браузера
На днях John Resig опубликовал в своем блоге интересную заметку Bad Object Detection, в которой размышляет на тему, того какие техники лучше не использовать при написании кроссбраузерных приложений. Хочу поговорить об этом подробнее.
Лично мне больше нравится техника, которую условно можно назвать “Object Detection”, т.е. это такой подход, при котором программист не должен определять версию и тип браузера, для того, чтобы решить какой объект или свойство использовать в программе. Вместо этого, проверяется наличие конкретного объекта, который предполагается использовать.
Прочитав заметку John-а я нашел еще один довод, в пользу своей точки зрения. Давайте рассмотрим такой код:
<html> <head> <script> window.onload = function(){ if ( window.opera ) { alert("You're using Opera, pick me!"); } }; </script> </head> <body> <h1>Which browser?</h1> <a href="http://mozilla.com/" id="firefox"> Firefox</a><br/> <a href="http://apple.com/" id="safari"> Safari</a><br/> <a href="http://opera.com/" id="opera"> Opera</a><br/> <a href="http://microsoft.com/" id="ie"> Internet Explorer</a> </body> </html>
Очевидно, что здесь свойство “window.opera” используется для того, чтобы определить загружена ли страница в Опере и если да, то вывести на экран соответствующее сообщение. На практике вместо alert-а, должен присутствовать кусок листинга который может исполняться только под Оперой.
Если запустить приведенный пример в нескольких популярных браузерах (Opera, IE, FireFox), то в результате - сообщение “You’re using Opera, pick me!” появляется не только в Opera, но и в Internet Explorer. Дело в том, что Internet Explorer интерпретирует ID как глобальную переменную и в результате у нас появляется четыре новых переменных с глобальной областью видимости - firefox, safari, opera и ie. Кстати, так же неправильно ведет себя KDE-ый браузер Konqueror, который тоже выносит ID в глобальную область видимости.
Даже если на стадии разработки программы, элементов с ID равным Opera точно не будет - не факт, что таких элементов не появится позже. Тем более, что данный баг IE, может проявляться не только в случае определения браузера. Даже, наверное, данный пример не самый удачный в плане того, что способ использования глобальной переменной для определения типа браузера - не самый распространенный.
В любом случае, поведение IE не является интуитивно понятным и прозрачным. Например, даже если знать, что все ID станут глобальными переменными, то все равно остается вопрос, что будет если в качестве значения ID будет использоваться строка состоящая из одних цифр (очевидно, что она не может быть именем переменной)? Или, что будет если в программе определена другая глобальная переменная с таким же именем, что ID?
Поэтому, чтобы не создавать себе лишних проблем лучше избегать подводных камней и, как я сказал ранее, использовать “object detection” по возможности избегая глобальных переменных вообще.
Octane
Гость
>> …что будет если в качестве значения ID будет использоваться строка состоящая из одних цифр…
Вообще на именование идентификаторов и классов накладываются такие же ограничения, как и для переменных в C-подобных языках, только еще разрешается символ «-» (дефис), поэтому если браузер поведет себя как-то странно в такой ситуации, мы не имеем права ругаться и кричать, что его написали какието идиоты. Странно конечно, для чего вообще сделали обработку неправильно названных идентификаторов и классов.
Zenitchik
Гость
>>очевидно, что она не может быть именем переменной
Вы забываете, что переменные глобального уровня являются свойствами окна. А идентификатором своиства может быть не только имя, но и номер, равно как и любая допустимая строка (насчёт значений других типов - не проверял).
Никакого конфликта: будет создано свойство, скажем window[32467].