The all attribute must return an HTMLAllCollection rooted at the Document node, whose filter matches all elements. The object returned for all has several unusual behaviors: The user agent must act as if the ToBoolean() operator in JavaScript converts the object returned for all to the false value.
all. Deprecated: This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes.
A falsy (sometimes written falsey) value is a value that is considered false when encountered in a Boolean context.
In JavaScript, a truthy value is a value that is considered true when encountered in a Boolean context. All values are truthy unless they are defined as falsy. That is, all values are truthy except false , 0 , -0 , 0n , "" , null , undefined , and NaN .
Disclaimer: I’m the guy who tweeted the question that led to this thread :) It was a question I would ask and answer in my Front-Trends talk. I wrote that tweet 5 minutes before going on stage.
The question I was asking is the following.
The ECMAScript spec defines ToBoolean()
as follows:
As you can see, all non-primitive objects (i.e. all objects that aren’t a boolean, a number, a string, undefined
, or null
) are truthy as per the spec. However, in the DOM, there is one exception to this — a DOM object that is falsy. Do you know which one that is?
The answer is document.all
. The HTML spec says:
The
all
attribute must return anHTMLAllCollection
rooted at theDocument
node, whose filter matches all elements.The object returned for all has several unusual behaviors:
The user agent must act as if the
ToBoolean()
operator in JavaScript converts the object returned forall
to thefalse
value.The user agent must act as if, for the purposes of the
==
and!=
operators in JavaScript, the object returned forall
is equal to theundefined
value.The user agent must act such that the
typeof
operator in JavaScript returns the string'undefined'
when applied to the object returned forall
.These requirements are a willful violation of the JavaScript specification current at the time of writing (ECMAScript edition 5). The JavaScript specification requires that the
ToBoolean()
operator convert all objects to thetrue
value, and does not have provisions for objects acting as if they wereundefined
for the purposes of certain operators. This violation is motivated by a desire for compatibility with two classes of legacy content: one that uses the presence ofdocument.all
as a way to detect legacy user agents, and one that only supports those legacy user agents and uses thedocument.all
object without testing for its presence first.
So, document.all
is the only official exception to this ECMAScript rule. (In Opera, document.attachEvent
etc. are falsy too, but that’s not specced anywhere.)
The above text explains why this was done. But here’s an example code snippet that’s very common on old web pages, and that will illustrate this further:
if (document.all) {
// code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
// code that uses `document.getElementById`, for “modern” browsers
}
Basically, for a long time document.all
was used in this way to detect old browsers. Because document.all
is tested first though, more modern browsers that offer both properties, would still end up in the document.all
code path. In modern browsers, we’d prefer to use document.getElementById
, of course, but since most browsers still have document.all
(for other backwards compatibility reasons) the else
would never be accessed if document.all
was truthy. Had the code been written differently, this wouldn’t be a problem:
if (document.getElementById) {
// code that uses `document.getElementById`, for “modern” browsers
} else if (document.all) {
// code that uses `document.all`, for ancient browsers
}
But sadly, a lot of existing code does it the other way around.
The simplest fix for this problem is to simply make document.all
be falsy in browsers that still mimic it.
There is now an [[IsHTMLDDA]] internal slot for objects:
An [[IsHTMLDDA]] internal slot may exist on implementation-defined objects. Objects with an [[IsHTMLDDA]] internal slot behave like
undefined
in the ToBoolean and Abstract Equality Comparison abstract operations and when used as an operand for thetypeof
operator.
The HTML Standard has also been updated to add that internal slot for objects that implement the HTMLAllCollection
interface:
Objects that implement the HTMLAllCollection interface are legacy platform objects with an additonal [[Call]] internal method described in the section below. They also have an [[IsHTMLDDA]] internal slot.
The reason for this madness is specified in this note in the HTML Standard:
These special behaviors are motivated by a desire for compatibility with two classes of legacy content: one that uses the presence of
document.all
as a way to detect legacy user agents, and one that only supports those legacy user agents and uses thedocument.all
object without testing for its presence first.
So basically the standard wants to be compatible with these two types of code:
Code that checks if it is running inside Internet Explorer to use its non-standard features, like document.all
and Activex;
if (document.all) {
useActiveXStuff();
}
Code that assumes it's running inside Internet Explorer and uses document.all
.
document.all["my-button"].onclick = function () {
alert("hi");
};
Modern browsers don't implement this outdated thing any more. It was introduced by IE, but most of the others "shim" it to be compatible.
To make browser detection possible (back in the old days you could tell IE apart from NN by testing for document.all
) while supporting document.all syntax, other browsers made the "weird" implementation that typeof document.all
returns undefined.
Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false
Before FF dropped support for it, it also showed weird behaviour as stated in this message. You may find more internals in Mozilla bug #412247.
There is also a very long thread in the W3C mailing list archive, beginning with http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html
In short, it's to make BOTH of these code samples work. Browsers have to do this so that old web pages will continue to work.
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
document.all.output.innerHTML = 'Hello, world!'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With