10

There is this tweet on Twitter:

In JavaScript, all objects are truthy (as per the spec). In the DOM, there’s one exception to this rule. What is it? #jsquiz #fronttrends

Does anyone know the answer?

Mathias Bynens
  • 144,855
  • 52
  • 216
  • 248
Nicola Peluchetti
  • 76,206
  • 31
  • 145
  • 192

4 Answers4

9

Disclaimer: I’m the guy who tweeted that :) It was a question I would ask and answer in my Front-Trends talk. I wrote that tweet 5 minutes before going on stage.


Because of the 140-character limit on Twitter, the question is slightly ambiguous. The real question I was asking is the following.

The ECMAScript spec defines ToBoolean() as follows:

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

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 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.

The user agent must act as if, for the purposes of the == and != operators in JavaScript, the object returned for all is equal to the undefined value.

The user agent must act such that the typeof operator in JavaScript returns the string 'undefined' when applied to the object returned for all.

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 the true value, and does not have provisions for objects acting as if they were undefined 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 of document.all as a way to detect legacy user agents, and one that only supports those legacy user agents and uses the document.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.)

Mathias Bynens
  • 144,855
  • 52
  • 216
  • 248
1

It is document.all.

It's non-standard, so you're better off using document.getElementsByTagName("*").

stusmith
  • 14,003
  • 7
  • 56
  • 89
1

Ok, using this code

for (var name in document) {
    if (!!document[name] === false && typeof document[name] === 'object' && document.hasOwnProperty(name)) {
        $('#foo').append('document.' + name + '<br />');        
    };
};​

i had this result in chrome (results may vary)

document.ownerDocument
document.attributes
document.namespaceURI
document.nextSibling
document.webkitCurrentFullScreenElement
document.nodeValue
document.preferredStylesheetSet
document.textContent
document.previousSibling
document.parentNode
document.xmlVersion
document.parentElement
document.localName
document.selectedStylesheetSet
document.prefix
document.xmlEncoding
Nicola Peluchetti
  • 76,206
  • 31
  • 145
  • 192
  • 1
    I’m afraid your test methodology is incorrect. For example, you’re missing a check for non-null values. Remember that we’re only talking about objects that aren’t primitives (so all objects that aren’t a boolean, a number, a string, `undefined`, or `null`). Also note that `typeof document.all == 'undefined'` even though it’s an object, so your test wouldn’t detect it. – Mathias Bynens May 01 '12 at 07:20
0

Just loop over the document and test all..

http://jsfiddle.net/UTNkW/3/

EDIT: Wrong test methodology, thankfully someone pointed it out and I could correct it.

GillesC
  • 10,647
  • 3
  • 40
  • 55
  • My test does detect it as it is in the list. My code take care of non-null value, that why there is 2 ! and not a single one, the first one will return true if the value is undefined, false or null and the second one will return false. if it didn't it would be in the list generated by the jsfiddle demo.... – GillesC May 01 '12 at 09:44
  • I’m afraid your test methodology is incorrect. For example, you’re missing a check for non-`null` values. Remember that we’re only talking about objects that aren’t primitives (so all objects that aren’t a boolean, a number, a string, `undefined`, or `null`). – Mathias Bynens May 01 '12 at 09:48
  • Your test returns some `null` values, which are primitive values. See `document.nextSibling`, for example. We’re only looking for objects that aren’t primitives. – Mathias Bynens May 01 '12 at 09:49
  • Ah yeah no my bad, got thrown away with the document.all comment, but I see what you mean, it's so obvious. – GillesC May 01 '12 at 09:50
  • hehe, not that tricky to be honest, but I just rushed in without taking it all in on that one :) – GillesC May 01 '12 at 09:54