Review of the NodeList API Proposal
original proposal available here.
Concerns
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
nodeTypeproperty. 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 thelengthproperty, and add values by index to a NodeList decorator.Additionally, if the NodeList decorator had an internal
[[Class]]ofArrayit 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 useaddEventListenerand friends to add listeners for a newaddandremoveevent 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.
A Fresh JavaScript Implementation
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.
Browser Support
Should support a wide range of browsers including:
- Chrome 1+
- Firefox 1.5+
- IE6+
- Opera 9.25+
- Safari 2.0.0+
Optimizations
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.
Editable
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().
Secure
The secured NodeList decorator is not exposed on an external property.
ES5 Compliant
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.
Future Proofing
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".
Tests and Benchmarks
Revised unit tests may be found here and benchmarks may be found here.
