- From: Jake Verbaten <raynos2@gmail.com>
- Date: Fri, 11 Nov 2011 14:12:12 +0000
- To: Jonas Sicking <jonas@sicking.cc>
- Cc: Webapps WG <public-webapps@w3.org>, public-script-coord@w3.org
- Message-ID: <CAMCMjp3mLwPnUC46teWQDJEhGzDo01OEZV7cw+Av8ksOga6Kuw@mail.gmail.com>
As a web developer, having DOM methods which return "real arrays" so we no longer have to call `toArray(nodeList)` or `[].slice.call(nodeList)` would be awesome. On Fri, Nov 11, 2011 at 9:05 AM, Jonas Sicking <jonas@sicking.cc> wrote: > Hi All, > > So, we've debated a lot the exact syntax for .find/.findAll. However I > intentionally requested that we split out the discussions about return > type for .findAll to a separate thread. So I'm starting that thread > here. > > There are a few goals for the return'ed object that I've envisioned > based on discussions so far: > > 1. It should have at least all of the non-mutating Array methods on > it. Possibly the mutating methods too if we allow the returned object > to be mutable. > 2. It should have a object on the prototype chain where we can insert > functions that are specifically useful for lists of nodes. Examples > include .find/.findAll/.matchesSelector/.remove/.addEventListener > 3. It would be good if it had the Array prototype object on it's > prototype chain so that if Array.prototype was extended, it would > affect this object too. > 4. The object will *not* be live since live results from selector > matching is slow. > > Since the returned object won't be live, I don't see a reason to make > it immutable. Hence it seems like we could put Array.prototype on the > prototype chain which would immediately make all non-mutating as well > as mutating functions available on the object. > > We should also insert a new prototype object in the prototype chain. > Hence we end up with something like: > > object -> [some type].prototype -> Array.prototype -> Object.prototype. > > And to ensure that the object acts as much as possible as an array it > should also have it's [[Class]] set to that of an array. This has > subtle effects on a number of functions. For example it affects what > Object.toString() and Array.isArray returns, it affects how > Array.concat behaves, and it affects the JSON serializer. > > I'm not sure if setting the [[Class]] to that of an array also gives > the object the magical .length property, but if it doesn't, we need to > also define that the returned object has such a property. Note that > for Arrays, .length doesn't live on the prototype chain, but is rather > a special property on the object itself. > > In other words, the returned object is exactly what you'd get if you did: > > a = new Array; > a.__proto__ = [some type].prototype; > [some type].prototype.__proto__ = Array.prototype; > > and then filled a with the set of nodes which matched the selector > passed to .findAll. > > > So the remaining question is, what should we use for [some type]. One > option is to use NodeList. However this would result in NodeLists > having Array.prototype on it's prototype chain. Including all mutating > functions. This is iffy in general since NodeLists are returned from > several APIs which return objects which represent a live result of a > query. For example .getElementsByTagName, .getElementsByClassName and > .childNodes. > Not to mention, that there must be a ton of code out there that assumes a nodeList is not an array (mediocre feature detection code). > > An additional source of iffiness with this idea is that several of the > mutating methods on Array.prototype don't throw if called on a > immutable objects. For example .pop, .shift, .sort and .reverse all > would not throw if called on an empty immutable list. > > Hence I propose that we add a new type. I don't care much for naming > things so I'll just suggest NodeArray for now and let others fight it > out over the name. > > For now we can leave NodeArray as empty and just let it be an > extension point for page authors. We can discuss separately if > .findAll/.matchesSelector should be added to NodeArray, and if so how > they should behave. > > However, we should probably use NodeArray to "fix" one of the problems > with some of the functions on Array.prototype. For example > Array.prototype.filter always returns a new Array object. This would > mean that: > > elem.findAll(...).filter(function(node) { ... }); > > will return a plain Array and not a NodeArray. However we could make > NodeArray override all such functions and keep their behavior > identical except that they return NodeArrays. > > Another way to fix this problem would be to change the definition of > Array.prototype.filter, but I have no idea if that's doable, or how > that would be done. > That would involve hackling with es-discuss. I send an email to their mailing list https://mail.mozilla.org/pipermail/es-discuss/2011-November/018242.html > > What do people think? > overall it's a great idea. It is however a shame we duplicate functionality with querySelectorAll > > / Jonas > >
Received on Friday, 11 November 2011 14:12:53 UTC