W3C home > Mailing lists > Public > whatwg@whatwg.org > July 2010

[whatwg] Adding ECMAScript 5 array extras to HTMLCollection

From: Ian Hickson <ian@hixie.ch>
Date: Fri, 30 Jul 2010 00:45:40 +0000 (UTC)
Message-ID: <Pine.LNX.4.64.1007300030090.7470@ps20323.dreamhostps.com>

The e-mails quoted below consist of the salient points of this thread:

On Fri, 23 Apr 2010, David Bruant wrote:
> 
> 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.

On Sun, 25 Apr 2010, J Z wrote:
> 
> 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
> });
> 
> // turning live collection into static array fixes this
> Array.slice(document.getElementsByTagName('div')).forEach(function(el) {
>   el.parentNode.removeChild(el);
> });

On Sat, 24 Apr 2010, David Bruant wrote:
>
> 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.

On Mon, 26 Apr 2010, Erik Arvidsson wrote:
> On Sun, Apr 25, 2010 at 01:07, David Bruant wrote:
> > Le 25/04/2010 00:39, J Z a ?crit?:
> >>
> >> 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?
> >
> > That is actually a very good point. It think that the behavior should 
> > be exactly the same as "an equivalent without array methods". (this 
> > point of my proposal would need to be made completly explicit for each 
> > method)
> 
> One way to solve this could be to split Array into two interfaces. One 
> to be used with immutable array like objects and one to use to mutate 
> objects. Then we could apply the immutable array like interface to 
> NodeList and its related interfaces. The benefit of doing that is that 
> NodeList.prototype.push would be undefined instead of failing when 
> called.

On Mon, 26 Apr 2010, David Flanagan wrote:
> 
> Rather that trying to make DOM collections feel like arrays, how about 
> just giving them a toArray() method?  This makes it clear that a 
> collection is not an array, but clearly defines a way to obtain an 
> array.  Clever implementors might even be able to optimize common 
> uses-cases using some kind of copy-on-write strategy so that toArray() 
> doesn't involve memory allocation and copying.
> 
> Of course, trying to teach programmers when they ought to call toArray() 
> and when it is not necessary is another matter.  Perhaps calling the 
> method snapshot() and focusing on the live vs. static distinction 
> instead of the fake array vs. true array distinction would invite less 
> misuse.
> 
> Or we can just leave the DOM as it is and get used to calling the 
> equivalent of Prototype's $A() function.

Before changing something this substantial, I'd like to have implementor 
feedback regarding what the best way to address this is:

 - somehow make HTMLCollections and NodeLists inherit from Array?

 - define a bunch of feature on HTMLCollections and NodeLists so that 
   they're like arrays?

 - provide a toArray() method or equivalent?

 - do nothing?

 - something else?

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
Received on Thursday, 29 July 2010 17:45:40 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 16:59:25 UTC