document.all
- это не примитивный объект в DOM, который является ложным.
Например, этот код ничего не делает:
if (document.all) {
alert("hello");
}
Может кто-нибудь объяснить, почему это?
document.all
- это не примитивный объект в DOM, который является ложным.
Например, этот код ничего не делает:
if (document.all) {
alert("hello");
}
Может кто-нибудь объяснить, почему это?
document.all
доступен только в Internet Explorer, webkit и Opera.
В каждом другом браузере all
является свойством undefined объекта document
(и undefined
считается ложным значением)
Как историческое примечание: многие (на самом деле многие) годы назад document.all
использовали, чтобы сообщить обозревателю Internet Explorer из Netscape Navigator, поэтому, если вы встретите script, который проверяет if (document.all) ...
, я настоятельно рекомендую найти лучший script:)
Отказ от ответственности: Я тот парень, который написал твиттер, который вызвал эту тему:) Это был вопрос я будет спрашивать и отвечать на мой разговор Front-Trends. Я написал этот твит за 5 минут до выхода на сцену.
Вопрос, который я задавал, следующий.
Спецификация ECMAScript определяет ToBoolean()
следующим образом:
Как вы можете видеть, все непримитивные объекты (т.е. все объекты, которые являются логическими, число, строка, undefined
или null
), являются правдивыми по спецификации. Однако в DOM есть одно исключение - объект DOM, который является ложным. Вы знаете, какой из них?
Ответ: document.all
. Спецификация HTML говорит:
Атрибут
all
должен вернутьHTMLAllCollection
, внедренный вDocument
node, фильтр которого соответствует всем элементам.Объект, возвращенный для всех, имеет несколько необычных типов поведения:
Пользовательский агент должен действовать так, как если бы оператор
ToBoolean()
в JavaScript преобразует возвращаемый объект дляall
в значениеfalse
.Пользовательский агент должен действовать так, как будто для
==
и!=
операторов в JavaScript, объект, возвращаемый дляall
, равенundefined
.Пользовательский агент должен действовать так, что оператор
typeof
в JavaScript возвращает строку'undefined'
при применении к возвращенному объектуall
.Эти требования являются преднамеренным нарушением JavaScript спецификация тока на момент написания (ECMAScript edition 5). Спецификация JavaScript требует, чтобы оператор
ToBoolean()
конвертировать все объекты в значениеtrue
и не имеет положений для объектов, действующих, как если бы они былиundefined
для целей некоторые операторы. Это нарушение мотивировано желанием совместимость с двумя классами устаревшего контента: тот, который использует наличиеdocument.all
в качестве способа обнаружения устаревших пользовательских агентов и который поддерживает только те устаревшие пользовательские агенты и используетdocument.all
объект без тестирования для его присутствия в первую очередь.
Итак, document.all
является единственным официальным исключением из этого правила ECMAScript. (В Opera, document.attachEvent
и т.д. Тоже ложны, но это нигде не указано.)
В приведенном выше тексте объясняется, почему это было сделано. Но heres примерный фрагмент кода, который очень распространен на старых веб-страницах, и это иллюстрирует это далее:
if (document.all) {
// code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
// code that uses `document.getElementById`, for "modern" browsers
}
В принципе, в течение длительного времени document.all
использовался таким образом для обнаружения старых браузеров. Поскольку сначала тестируется document.all
, но более современные браузеры, предлагающие оба свойства, все равно попадают в путь кода document.all
. Конечно, в современных браузерах предпочитают использовать document.getElementById
, но поскольку большинство браузеров по-прежнему имеют document.all
(для других соображений обратной совместимости), else
никогда не будет доступен, если document.all
был правдивым. Если бы код был написан по-разному, это не было бы проблемой:
if (document.getElementById) {
// code that uses `document.getElementById`, for "modern" browsers
} else if (document.all) {
// code that uses `document.all`, for ancient browsers
}
Но, к сожалению, многие существующие коды делают это по-другому.
Простейшим решением этой проблемы является просто сделать document.all
ложным в браузерах, которые все еще имитируют.
Вкратце, это сделать ОБА этих образцов кода работать. Браузеры должны сделать это, чтобы старые веб-страницы продолжали работать.
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
document.all.output.innerHTML = 'Hello, world!'
Современные браузеры уже не реализуют эту устаревшую вещь. Он был введен IE, но большинство других "подгоняют" его, чтобы быть совместимым.
Чтобы сделать возможным обнаружение браузера (в прежние времена вы могли бы рассказать IE отдельно от NN путем тестирования для document.all
), поддерживая синтаксис document.all, другие браузеры сделали "странную" реализацию, которая typeof document.all
возвращает undefined.
Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false
До того, как FF потерял поддержку для нее, она также показала странное поведение, как указано в это сообщение. Вы можете найти больше внутренних элементов в Ошибка Mozilla # 412247.
В архиве списков рассылки W3C есть также очень длинный поток, начиная с http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html
document.all - не единственный объект, который является ложным. Другой вопрос был опубликован об этом, и в качестве примера скрипта в ответе показано, что в документе много фальсифицированного объекта. Сумма зависит от используемого браузера.
См. этот вопрос Все объекты в JavaScript являются правдивыми по спецификации, но в DOM один не примитивный объект не является. Что?
И скрипка, отображающая весь фальшивый объект документа http://jsfiddle.net/UTNkW/
Хорошо, назовите меня lazy @@@, проголосуйте за меня и подумайте, что я еретик, но поскольку jQuery сбросил $.browser, я перезапустил его, чтобы быстро и грязно обнаружить браузер.
Позвольте мне объяснить, почему и когда: я не хочу проверять, поддерживает ли какая-либо конкретная (вспомогательная) версия IE, и я не хочу добавлять плагины или настраиваемые функции, которые не всегда работают или должны быть обновлены или даже заменены каждый раз, когда Microsoft выпускает обновление, я просто хочу знать, нужно ли мне добавить setTimeout в мою функцию init, чтобы избежать зависания или зависания IE, и не хотите наносить вред более надежным браузерам в процессе.
Пожалуйста, будьте честны, мы все знаем, что Microsoft НИКОГДА не откажется от нее (для обратной совместимости с веб-серверами крупных компаний, основанными только на IE, может ли Господь их простить), а другие поставщики браузеров будут следовать, как это всегда было с тех пор (не столь незаслуженная) смерть Netscape.
И ИМХО, это также поведение, совместимое с HTML5;)