[whatwg] Adding ECMAScript 5 array extras to HTMLCollection

Le 24/04/2010 22:50, J Z a ?crit :
> On Fri, Apr 23, 2010 at 10:30 PM, David Bruant 
> <bruant at enseirb-matmeca.fr <mailto:bruant at enseirb-matmeca.fr>> wrote:
>
>     Hi,
>
>     In the HTML5 "status of this document" section, one can read :
>     "This specification is intended to replace (be the new version of)
>     what was previously the [...] DOM2 HTML specifications."
>     This spec can be found here : http://www.w3.org/TR/DOM-Level-2-HTML/
>
>     It defines ECMAScript language Binding
>     (http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html).
>     This document explains how to implement the DOM HTML interfaces in
>     an ECMAScript-compliant environment.
>
>     Because HTML5 is intended to replace DOM2 HTML, it can "freely"
>     change ECMAScript bindings. My suggestion is the following :
>     Make that HTMLCollection (and all HTML*Collection, as a
>     consequence of inheritence of HTMLCollection) inherit from the
>     ECMAScript Array prototype. This way, it will make available all
>     Array extra methods (forEach, map, filter...) added in ECMAScript5
>     (and next versions which should go in the same direction).
>
>     As far as I know, adding this won't break any existing code. The
>     semantics of a Collection and the way it is used is very close
>     from ECMAScript Arrays.
>     I don't think that the notion of "live object" and ECMAScript
>     Array are incompatible either.
>     Once again, I am talking about ECMAScript binding. I have no
>     intention to touch the HTMLCollection interface or other languages
>     bindings.
>
>     Would the WHATWG have the power to decide something similar
>     regarding NodeList ?
>
>     Any thoughts ?
>
>     Thanks,
>
>     David
>
>
> As far as I can see, liveness of HTMLCollection actually does matter. 
> When iterating over HTMLCollection, it's more or less a rule of thumb 
> to "save" length, to avoid any kind of mismatch (in case code within 
> loop modifies document and so affects length of collection in question):
>
> for (var i = 0, length = collection.length; i < length; i++)
> // instead of:
> for (var i = 0; i < collection.length; i++)
I think I can take your point as a "pro" more than a "con", because in 
ES5, right before the definition of each array extra method, a paragraph 
like the following can be found :
"The range of elements processed by forEach is set before the first call 
to callbackfn. Elements which are appended to the array after the call 
to forEach begins will not be visited by callbackfn. If existing elements of
the array are changed, their value as passed to callback will be the 
value at the time forEach visits them; elements that are deleted after 
the call to forEach begins and before being visited are not visited."

This point is confirmed by every algorithm where the length is "saved" 
once for all before the loop and not got from the .length property each 
time.


>
> If HTMLCollection was inheriting from Array, and methods like 
> `forEach`, `map`, etc. were to operate on a live object, there would 
> definitely be undesired consequences. We can see this in, say, Firefox 
> (which allows to set [[Prototype]] of `HTMLCollection` to 
> `Array.prototype`):
>
> HTMLCollection.prototype.__proto__ = Array.prototype;
>
> document.getElementsByTagName('div').forEach(function(el) {
>   el.parentNode.removeChild(el); // doesn't work as expected
> });
This code doesn't work as expected as the following doesn't either :
var divs = document.getElementsByTagName('div');
for(var i=0, l = divs.length ; i < l ; i++){
     var el = divs[i]; // Due to the live-ness, this might not work as 
expected
     el.parentNode.removeChild(el);
}

This code written as a for-loop behave exactly the same way (in this 
case) as the .forEach one, so it's as buggy as the forEach one.
My point is that forEach doesn't create more bugs than before, which is 
what you seem to imply.
Adding .forEach and other Array extras wouldn't prevent programmers to 
remember that they are dealing with a live object even within a 
.forEach, the same way they are not supposed to forget it with a for-loop.

I have thought a lot about weirdnesses that people could think about 
like trying to assign a value to the HTMLCollection (divs[14] = 
myOtherDiv), but once again, it wouldn't be more allowed than it 
currently is (I have no idea of what happens today, but if an error is 
thrown in a for-loop, it should throw an error as well in a call within 
a forEach).


This has nothing to do with this thread, but 
document.getElementsByTagName('div') should return a NodeList 
(http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-A6C9094). Returning 
an HTMLCollection is a Firefox bug 
(https://bugzilla.mozilla.org/show_bug.cgi?id=14869).


>
> // turning live collection into static array fixes this
>
> Array.slice(document.getElementsByTagName('div')).forEach(function(el) {
>   el.parentNode.removeChild(el);
> });
I have not found anything about a Array.slice method and the ES5 .splice 
method doesn't seem to by usable in the way you describe. What did you 
mean ?

The idea of turning the live object into a static array seems to be an 
interesting one for some cases, but once again a problem you could solve 
with a for-loop (in a live object or not like the results of 
querySelectorAll) can be solved with a .forEach.
On the other side, the equivalent for-loop (according to the ES5 spec) 
of a buggy forEach will be buggy as well.

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20100424/9a2ab434/attachment.htm>

Received on Saturday, 24 April 2010 23:33:53 UTC