<br><br><div class="gmail_quote">On Sun, Apr 25, 2010 at 2:33 AM, David Bruant <span dir="ltr"><<a href="mailto:bruant@enseirb-matmeca.fr" target="_blank">bruant@enseirb-matmeca.fr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">





  

<div text="#000000" bgcolor="#ffffff">
Le 24/04/2010 22:50, J Z a écrit :
<div><blockquote type="cite">On Fri, Apr 23, 2010 at 10:30 PM, David Bruant <span dir="ltr"><<a href="mailto:bruant@enseirb-matmeca.fr" target="_blank">bruant@enseirb-matmeca.fr</a>></span>
wrote:<br>
  <div class="gmail_quote">
  <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hi,<br>
    <br>
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."<br>
This spec can be found here : <a href="http://www.w3.org/TR/DOM-Level-2-HTML/" target="_blank">http://www.w3.org/TR/DOM-Level-2-HTML/</a><br>
    <br>
It defines ECMAScript language Binding (<a href="http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html" target="_blank">http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html</a>).
This document explains how to implement the DOM HTML interfaces in an
ECMAScript-compliant environment.<br>
    <br>
Because HTML5 is intended to replace DOM2 HTML, it can "freely" change
ECMAScript bindings. My suggestion is the following :<br>
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).<br>
    <br>
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.<br>
I don't think that the notion of "live object" and ECMAScript Array are
incompatible either.<br>
Once again, I am talking about ECMAScript binding. I have no intention
to touch the HTMLCollection interface or other languages bindings.<br>
    <br>
Would the WHATWG have the power to decide something similar regarding
NodeList ?<br>
    <br>
Any thoughts ?<br>
    <br>
Thanks,<br>
    <font color="#888888"><br>
David<br>
    </font></blockquote>
  </div>
  <br>
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):<br>
  <br>
for (var i = 0, length = collection.length; i < length; i++)<br>
// instead of:<br>
for (var i = 0; i < collection.length; i++)<br>
</blockquote></div>
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 : <br>
"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<br>
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."<br>
<br>
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.</div></blockquote><div><br>Oh, perfect :)<br>
<blockquote type="cite"><br>
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`):<br>
  <br>
HTMLCollection.prototype.__proto__ = Array.prototype;<br>
  <br>
document.getElementsByTagName('div').forEach(function(el) {<br>
  el.parentNode.removeChild(el); // doesn't work as expected<br>
});<br>
</blockquote></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div text="#000000" bgcolor="#ffffff">
This code doesn't work as expected as the following doesn't either : <br>
var divs = document.getElementsByTagName('div');<br>
for(var i=0, l = divs.length ; i < l ; i++){<br>
    var el = divs[i]; // Due to the live-ness, this might not work as
expected<br>
    el.parentNode.removeChild(el);<br>
}<br>
<br>
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.<br></div></blockquote><div><br>Sorry, that was a stupid example indeed. It should have been at least something along the lines of:<br><br>var els = document.getElementsByTagName('span');<br>
<br>for (var i = 0; i < els.length; /* can't access length dynamically */ i++) {<br>  var spanEl = document.createElement('span');<br>  spanEl.appendChild(document.createTextNode('foo'));<br>  document.body.appendChild(spanEl);<br>
}<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div text="#000000" bgcolor="#ffffff">
My point is that forEach doesn't create more bugs than before, which is
what you seem to imply.<br></div></blockquote><div><br>If it operates on "static" collection, then I don't see problems either.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div text="#000000" bgcolor="#ffffff">
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.<br></div></blockquote><div><br>Sure.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div text="#000000" bgcolor="#ffffff">

<br>
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).<br></div></blockquote><div><br>How would destructive methods like `push` or `sort` behave? Would `document.body.childNodes.push(document.createTextNode('foo'))` append text node to a body element? Or would it be a noop?<br>
 </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div text="#000000" bgcolor="#ffffff"><br><div><blockquote type="cite">
// turning live collection into static array fixes this<br>
  <br>
Array.slice(document.getElementsByTagName('div')).forEach(function(el) {<br>
  el.parentNode.removeChild(el);<br>
});<br>
</blockquote></div><br>

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 ?<br></div></blockquote><div><br>That's array generics in Mozilla (<a href="https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_and_String_generics">https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_and_String_generics</a>). I used it for brevity, but it could have been standard `Array.prototype.slice.call(collection, 0)` instead (in environments which allow such conversion of course). <br>
<br>[...]<br><br>-- <br>kangax<br>
</div></div>