Почему document.all ложь?

document.all - это не примитивный объект в DOM, который является ложным.

Например, этот код ничего не делает:

if (document.all) {
    alert("hello");
}

Может кто-нибудь объяснить, почему это?

Ответы

Ответ 1

document.all доступен только в Internet Explorer, webkit и Opera.

В каждом другом браузере all является свойством undefined объекта documentundefined считается ложным значением)

Как историческое примечание: многие (на самом деле многие) годы назад document.all использовали, чтобы сообщить обозревателю Internet Explorer из Netscape Navigator, поэтому, если вы встретите script, который проверяет if (document.all) ..., я настоятельно рекомендую найти лучший script:)

Ответ 2

Отказ от ответственности: Я тот парень, который написал твиттер, который вызвал эту тему:) Это был вопрос я будет спрашивать и отвечать на мой разговор Front-Trends. Я написал этот твит за 5 минут до выхода на сцену.


Вопрос, который я задавал, следующий.

Спецификация ECMAScript определяет ToBoolean() следующим образом:

ToBoolean(condition), slide from my Front-Trends 2012 talk

Как вы можете видеть, все непримитивные объекты (т.е. все объекты, которые являются логическими, число, строка, 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 ложным в браузерах, которые все еще имитируют.

Ответ 3

Вкратце, это сделать ОБА этих образцов кода работать. Браузеры должны сделать это, чтобы старые веб-страницы продолжали работать.

Пример 1

// Internet Explorer
if (document.all) {
    useActiveX()
}
// Netscape Navigator
else {
    useOldButStillWorkingCode()
}

Образец 2

document.all.output.innerHTML = 'Hello, world!'

Ответ 4

Современные браузеры уже не реализуют эту устаревшую вещь. Он был введен 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

Ответ 5

document.all - не единственный объект, который является ложным. Другой вопрос был опубликован об этом, и в качестве примера скрипта в ответе показано, что в документе много фальсифицированного объекта. Сумма зависит от используемого браузера.

См. этот вопрос Все объекты в JavaScript являются правдивыми по спецификации, но в DOM один не примитивный объект не является. Что?

И скрипка, отображающая весь фальшивый объект документа http://jsfiddle.net/UTNkW/

Ответ 6

Хорошо, назовите меня lazy @@@, проголосуйте за меня и подумайте, что я еретик, но поскольку jQuery сбросил $.browser, я перезапустил его, чтобы быстро и грязно обнаружить браузер.

Позвольте мне объяснить, почему и когда: я не хочу проверять, поддерживает ли какая-либо конкретная (вспомогательная) версия IE, и я не хочу добавлять плагины или настраиваемые функции, которые не всегда работают или должны быть обновлены или даже заменены каждый раз, когда Microsoft выпускает обновление, я просто хочу знать, нужно ли мне добавить setTimeout в мою функцию init, чтобы избежать зависания или зависания IE, и не хотите наносить вред более надежным браузерам в процессе.

Пожалуйста, будьте честны, мы все знаем, что Microsoft НИКОГДА не откажется от нее (для обратной совместимости с веб-серверами крупных компаний, основанными только на IE, может ли Господь их простить), а другие поставщики браузеров будут следовать, как это всегда было с тех пор (не столь незаслуженная) смерть Netscape.

И ИМХО, это также поведение, совместимое с HTML5;)