- From: J Z <kangax.dev@gmail.com>
- Date: Sun, 25 Apr 2010 03:39:39 -0400
On Sun, Apr 25, 2010 at 2:33 AM, David Bruant <bruant at enseirb-matmeca.fr>wrote: > 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>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. > Oh, perfect :) 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. > Sorry, that was a stupid example indeed. It should have been at least something along the lines of: var els = document.getElementsByTagName('span'); for (var i = 0; i < els.length; /* can't access length dynamically */ i++) { var spanEl = document.createElement('span'); spanEl.appendChild(document.createTextNode('foo')); document.body.appendChild(spanEl); } > My point is that forEach doesn't create more bugs than before, which is > what you seem to imply. > If it operates on "static" collection, then I don't see problems either. > 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. > Sure. > > 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). > 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? > > // 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 > ? > That's array generics in Mozilla ( https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_and_String_generics). 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). [...] -- kangax -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20100425/db7f0b76/attachment.htm>
Received on Sunday, 25 April 2010 00:39:39 UTC