[Bug 19045] New: Consider adding .toArray() on NodeList and HTMLCollection

https://www.w3.org/Bugs/Public/show_bug.cgi?id=19045

           Summary: Consider adding .toArray() on NodeList and
                    HTMLCollection
           Product: HTML WG
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: NoReply
          Severity: enhancement
          Priority: P5
         Component: HTML5 spec
        AssignedTo: dave.null@w3.org
        ReportedBy: contributor@whatwg.org
         QAContact: public-html-bugzilla@w3.org
                CC: mike@w3.org, public-html-wg-issue-tracking@w3.org,
                    public-html@w3.org, simonp@opera.com,
                    crisp@tweakers.net, aaz@odnorazovoe.ru,
                    slightlyoff@google.com


This was was cloned from bug 5851 as part of operation LATER convergence.
Originally filed: 2008-07-10 06:53:00 +0000
Original reporter: Ian 'Hixie' Hickson <ian@hixie.ch>

================================================================================
 #0   Ian 'Hixie' Hickson                             2008-07-10 06:53:33 +0000 
--------------------------------------------------------------------------------
>From http://alex.dojotoolkit.org/?p=623 :

Fast LiveCollection -> Array Transforms: That many DOM apis return live
collections is a bug, but it need not be fatal. Browser vendors could start to
provide a simple toArray() method on these live collections to provide a way to
“fix” them in place.
================================================================================
 #1   crisp                                           2008-07-10 23:04:05 +0000 
--------------------------------------------------------------------------------
'live collections' are not a bug; they are a design feature and you could use
that to your advantage. They are on the other side often misunderstood or not
anticipated which could lead to bugs or unexpected results.

On the other hand it is already quite easy to convert such collections to an
array in a browser that has implemented Array in a generic way so that it also
works on interface objects:

var foo = document.getElementsByTagName('div');
var staticFoo = [].slice.call(foo, 0);

the toArray() could then easily be implemented by prototyping NodeList or
HTMLCollection (don't know which one or which browsers actually support that)

I'd rather see a specification that says that Array methods should be generic
and thus also work on interface objects (that can be accessed like an array
having a length property and all) and that interface objects should be
first-class javascript objects and thus be expandable.
================================================================================
 #2   crisp                                           2008-07-11 00:21:14 +0000 
--------------------------------------------------------------------------------
In addition: the performance element brought by alex is just a straw hat; most
of the time core JS and DOM operations are just a fraction of dynamic HTML
updates. (partial) Document re-rendering is mostly more time consuming.
================================================================================
 #3   Lachlan Hunt                                    2008-07-11 08:03:42 +0000 
--------------------------------------------------------------------------------
(In reply to comment #1)
> 'live collections' are not a bug; they are a design feature and you could use
> that to your advantage.

Even though it's by design, some people consider it a bug because it's very
unintuitive.

> On the other hand it is already quite easy to convert such collections to an
> array in a browser that has implemented Array in a generic way so that it also
> works on interface objects:
> 
> var foo = document.getElementsByTagName('div');
> var staticFoo = [].slice.call(foo, 0);


> the toArray() could then easily be implemented by prototyping NodeList or
> HTMLCollection (don't know which one or which browsers actually support that)

It's good to know that it can be so easily provided like that for backwards
compatibility, but it's likely that a native implementation would be a bit more
efficient.

> I'd rather see a specification that says that Array methods should be generic
> and thus also work on interface objects (that can be accessed like an array
> having a length property and all) and that interface objects should be
> first-class javascript objects and thus be expandable.

This can't work because NodeLists are live (except in Selectors API).  If they
weren't live, it would have been possible to consider something like that.

Consider what it would mean for some of the mutator methods of Array to be used
directly on a NodeList. e.g.

var foo = document.getElementsByTagName('div');
foo.reverse();
foo.pop();
...

The toArray() method solves this problem, since one can easily do:

var foo = document.getElementsByTagName('div').toArray();

and not have to deal with the NodeList any more.
================================================================================
 #4   crisp                                           2008-07-11 08:20:50 +0000 
--------------------------------------------------------------------------------
If efficiency is key than it makes more sense to add an extra argument to the
method that says it's to return a static array iso a live nodelist. That way
you're even allowed to do this:

var foo = document.getElementsByTagName('div', RETURN_STATIC_ARRAY).reverse();

:)
================================================================================
 #5   Lachlan Hunt                                    2008-07-11 08:59:21 +0000 
--------------------------------------------------------------------------------
(In reply to comment #4)
> If efficiency is key than it makes more sense to add an extra argument to the
> method that says it's to return a static array iso a live nodelist. That way
> you're even allowed to do this:
> 
> var foo = document.getElementsByTagName('div', RETURN_STATIC_ARRAY).reverse();

That's not backwards compatible and makes it more difficult for JS libraries to
provide the functionality in legacy browsers.  It would require the script to
do replace the method itself, check for the extra paramter and return an array.

document._getElementsByTagName = document.getElementsByTagName;
document.getElementsByTagName = function(tagName, static) {
  var list = document._getElementsByTagName(tagName);
  if (static) {
    var array = [].slice.call(foo, 0);
    return array;
  }
  return list;
}

That would also have to be done separately for every other existing and future
method that returns a NodeList on both document and the element nodes.  Adding
a single method that deals with all node lists regardless of where they come
from is much easier to implement and use.
================================================================================
 #6   crisp                                           2008-07-11 09:49:24 +0000 
--------------------------------------------------------------------------------
The same goes for toArray(), you do need to implement switching logic anyway
because this simply will not work either:

var foo = document.getElementsByTagName('div').toArray();

and afaik there is no way in legacy browsers to make this work since one
browser doesn't support expando's on interface objects *at all* and I can't
even make this work in at least Firefox:

if (!HTMLCollection.prototype.toArray)
{
 HTMLCollection.prototype.toArray = function()
 {
  return [].slice.call(this, 0);
 }
}

(assuming this is the right object, I tried NodeList too for good measure)

the only option is to prototype toArray on Object, and we all know that that's
not good practice.

Imo a generic toArray method for live nodelists is just syntax sugering and
doesn't really solve the problem of the concept of live nodelists being
unintuitive; you will need to know about the fact anyhow to know that you can
use toArray() (in some unforeseeable future).

And like I said: if performance is key a native toArray method is far less
performant than an extra argument. And how much will it's performance gain be
over [].slice.call? Will that be worth the trouble?
================================================================================
 #7   Ian 'Hixie' Hickson                             2009-05-24 01:07:51 +0000 
--------------------------------------------------------------------------------
In the interests of not getting ahead of the implementations, I'm going to punt
on this for now. I think it makes sense to do something like this (I've even
suggested the same myself years ago).
================================================================================
 #8   Maciej Stachowiak                               2010-03-14 13:15:11 +0000 
--------------------------------------------------------------------------------
This bug predates the HTML Working Group Decision Policy.

If you are satisfied with the resolution of this bug, please change the state
of this bug to CLOSED. If
you have additional information and would like the editor to reconsider, please
reopen this bug. If you would like to escalate the issue to the full HTML
Working Group, please add the TrackerRequest keyword to this bug, and suggest
title and text for the tracker issue; or you may create a tracker issue
yourself, if you are able to do so. For more details, see this document:
   http://dev.w3.org/html5/decision-policy/decision-policy.html

This bug is now being moved to VERIFIED. Please respond within two weeks. If
this bug is not closed, reopened or escalated within two weeks, it may be
marked as NoReply and will no longer be considered a pending comment.
================================================================================

-- 
Configure bugmail: https://www.w3.org/Bugs/Public/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.

Received on Tuesday, 25 September 2012 21:59:28 UTC