One of the lesser known HTML5 JavaScript goodies is the document.head DOM tree accessor, which is a more efficient (and easier to type) alternative to document.getElementsByTagName('head')[0].
The
headelement of a document is the firstheadelement that is a child of thehtmlelement, if there is one, ornullotherwise. Theheadattribute, on getting, must return theheadelement of the document (aheadelement ornull).
Native support for document.head is very easy to detect:
if (document.getElementsByTagName('head')[0] === document.head) {
// Native support
}
Emulating it is also very straightforward. Just put the following snippet in your JavaScript code:
document.head = document.head || document.getElementsByTagName('head')[0];
If you don’t care about JSLint booing at your code, you could also do this instead (which is slightly more efficient):
document.head || (document.head = document.getElementsByTagName('head')[0]);
After that, go ahead and use document.head all you want :)
Comments
Paul Irish wrote on :
If you wanna be even more efficient:
:)
Mathias wrote on :
Paul Irish: Nice! Too bad JSLint complains about it:
Framp wrote on :
Simple is beautiful.
Raynos wrote on :
Curly braces are beautiful.
Adrusi wrote on :
Block scope is beautiful.
Federico wrote on :
Adrusi: How is that even needed? Care to help us understand (via links, search keywords, etc.)?
Lea Verou wrote on :
The problem with these polyfills is that on new iframes
document.headstill won’t exist, so they’re imperfect. Not sure how to solve that in a sensible manner though, but I’d really like to see adocument.headpolyfill one can really rely on.Mathias wrote on :
Lea: That’s a fair point.
Personally I’m fine with just using the above snippet (it’s not really a polyfill in the strict sense of the word) once for every frame I need it for. Most of the time I need a reference to the
<head>element in a given document, I end up caching it like this:It’s so small and fast it doesn’t really hurt to repeat it for a different frame when needed.
Matt wrote on :
Federico: Block scope is completely pointless in that case. There's nothing to be scoped.
Adam wrote on :
Doesn’t seem to work anymore in Chrome 14. It just says “Uncaught ReferenceError: Invalid left-hand side in assignment” in the console. This works, however:
Tested and works in the latest WebKit/Gecko/Opera. Here’s the output from testing IE 5.5 to 10, Chrome 14 and iPad Safari 4.3.1 in Tutti.
Ad@m
Mathias wrote on :
Adam: What doesn’t work? I can’t reproduce any issues with the code in the blog post.
MaxArt wrote on :
JSLint is a disgrace for all the JavaScript code artists.
It just doesn’t understand the power of JavaScript’s syntax.
Paul’s solution is the kind that I usually adopt.