- From: Brendan Eich <brendan@mozilla.org>
- Date: Fri, 11 Nov 2011 10:06:39 -0800
- To: Jonas Sicking <jonas@sicking.cc>
- Cc: WebApps WG <public-webapps@w3.org>, public-script-coord@w3.org, Allen Wirfs-Brock <allenwb@mozilla.com>
On Nov 11, 2011, at 1:05 AM, Jonas Sicking 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 is not something to do lightly -- at least cross-post the first message to es-discuss@mozilla.org and set reply-to followups-to. Cc'ing Allen. Note that [[Class]] is going away in ES.next. The internal methods and properties of ECMA-262 are not arbitrary extension points for other specs to use without consultation. /be > 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. > > 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. > > > What do people think? > > / Jonas >
Received on Friday, 11 November 2011 18:07:19 UTC