original proposal available here.
I think adding sugar to the NodeList interface or creating a special decorator via document.createNodeList()
is an awesome idea.
However, I have a few concerns / issues with Resig's current proposal.
-
The NodeList decorator should not have a
nodeType
property. It's not a node and cannot be inserted into other nodes.(Though an insertable list would be neat. InsertableList anyone?)
-
The developer should be able to
pop()
,push()
,shift()
,splice()
,unshift()
, change thelength
property, and add values by index to a NodeList decorator.Additionally, if the NodeList decorator had an internal
[[Class]]
ofArray
it would virtually eliminate the need fortoArray()
and allow the decorator to masquerade as an array enabling its use in popular JavaScript frameworks and methods like Function#apply. -
The NodeList decorator should not use callback methods
added()
orremoved()
. Instead it should useaddEventListener
and friends to add listeners for a newadd
andremove
event type. -
What's the real world use for a
secure()
method? It seems like a lot of work to implement and easy for a developer to bypass by simply querying the document again to access the elements they want. -
The
requery()
method seems overly complex and restrictive. If a developer needs a fresh NodeList decorator they can simply pass another DOM List (DOM NodeList, HTMLCollection, StaticNodeList) todocument.createNodeList()
. The baggage of maintaining a history and then limiting NodeList decorators to readonly access seems like a step in the wrong direction.
With that said I have written my own JavaScript implementation inspired by John Resig's NodeList proposal. It uses sandboxed arrays so the object returned from document.createNodeList()
is a real array.
Should support a wide range of browsers including:
- Chrome 1+
- Firefox 1.5+
- IE6+
- Opera 9.25+
- Safari 2.0.0+
The implementation is optimized for the common use case of passing a DOM List to document.createNodeList()
.
Because the output is a real array you don't need to worry about converting the NodeList decorator for use
with Function#apply or other methods that expect an array.
Feel free to use pop()
, push()
, shift()
, splice()
, unshift()
, change the length
property, and add values
by index to the NodeList decorator. Keep in mind that doing so will break the link between the original DOM List and requery()
.
The secured NodeList decorator is not exposed on an external property.
Array methods on the NodeList decorator follow the ES5 specification.
This means concat()
allows more than one argument, forEach()
does not
return an object reference, filter()
throws a TypeError
if callback is not a function,
and objects passed to document.createNodeList()
aren't required to have a length
property.
The implementation does not extend DOM object prototypes because they are too hard to maintain and would most likely cause problems for future browser releases. For more information on why extending DOM object prototypes is verboten please read Kangax's post "What's wrong with extending the DOM".
Revised unit tests may be found here and benchmarks may be found here.