W3C home > Mailing lists > Public > www-dom@w3.org > October to December 2011

Re: toArray() method for array-like DOM list objects

From: Marat Tanalin | tanalin.com <mtanalin@yandex.ru>
Date: Tue, 27 Dec 2011 03:20:58 +0400
To: Boris Zbarsky <bzbarsky@mit.edu>
Cc: www-dom@w3.org
Message-Id: <65541324941658@web81.yandex.ru>


24.12.2011, 03:50, "Boris Zbarsky" <bzbarsky@MIT.EDU>:
> On 12/23/11 11:13 AM, Marat Tanalin | tanalin.com wrote:
>
>> Actually, this is workaround use of slice() too: for making a copy of an array, we should have dedicated clone() method intended exactly to make Array copies and thus is more intuitive than slice() for this specific purpose.
>
> This could then just be generic like other array methods, and you could
> use it to clone any arraylike. Sounds fin to me.

Not exactly. Here I implied Array objects only. But if try to generalize, then any (not just Array or array-like) object could have native clone() method. Cloning objects is one of often tasks in JS.

>>>>> Or this object:
>>>>> { length: 2, 0: "a", 1: "b" }
>>>> Result of calling Array.prototype.slice.call() for this object is unlikely to be desired:
>>>> [a,b]
>>> Why is that unlikely to be desired? That's exactly the Array object
>>> that has the same behavior when iterated from 0 to length as the
>>> original array.
>> We have assotiative-array-like object with three items
>
> What if the "length" property there were not enumerable? Pretty simple
> to create an object like that.
>
>> I think this is bad consequence of too much abstraction of Array-like definition based on length property existence.
>
> It's the standard definition in ECMAScript.

It's probably too common definition then. Maybe it's OK for ECMAScript though.

>>>> Direct conversion to Array is probably just inapplicable here.
>>> Why not?
>> Array is list thing while assotiative-array-like object is map. They're just not equivalent things that can be freely converted to each other lossless way.
>
> Consider the following situations:
>
> var obj1 = new Array();
> obj1[0] = "x";
> obj1["z"] = "y";
>
> var obj2 = new Object();
> obj2[0] = "x";
> obj2["z"] = "y";
> Object.defineProperty(obj2, "length",
> { value: 2, writable: true,
> configurable: true, enumerable: false });
>
> What are the exact differences between obj1 and obj2 as long as you
> don't plan to modify them (so you're just reading data you were passed)?

Using Array object (instead of pure Object) as associative array is usually considered bad practice because Array's length property does not reflect items with nonnumeric keys.

>>> Precisely. But how is [a, b] really different from { length: 2, 0: "a",
>>> 1: "b" } from a web-developer perspective?
>> We actually should compare DOM list with Array, not array with assotiative-array-like object.
>
> I think you have a pretty confused understanding of how Arrays work in
> ECMAScript. They're just another associative-array-like object whose
> prototype happens to be Array.prototype, and with some special behavior
> around changes to the "length" property.

That "some special behavior" does matter, I think.

>> Generation of DOM lists is outside of web-developer control, that's why we need a convenient way to convert it to Array.
>
> Generation of a function's input is outside that function's control by
> definition. That's my point: it's not clear to me why from the point of
> view of the _callee_ there should be a difference between arrays and
> nodelists if you want to just make a copy of your input.

If it's needed to just make a copy of an object, it's should be possible to call its common clone() method that in particular should care about possible object-type's special characteristics. In general, a specific (not one of language's basic types like String or Array) type can and should know about how to be converted into basic type, but a basic type (e.g. String or Array) cannot be familiar with all other types of objects in the world. Maybe this is not the case for ECMAScript (I'm not a hardcore ECMAScript guru), but anyway ECMA/JS APIs probably would be more consistent with other languages like PHP and thus more intuitive. For example, in PHP:

	$list  = array('length', 'foo', 'bar');

	$assoc = array(
		'length' => 2,
		'foo' => 'lorem',
		'bar' => 'ipsum'
	);

length (result of standard count() function) of both list ($list) and associative array ($assoc) would be 3 (and yes, I know that arrays are objects in JS and are not in PHP).

>>> Sure. What do you think
>>>
>>> new Array(5)
>>>
>>> does? How does that compare to
>>>
>>> new Array("x")
>>>
>>> ?
>> Never used such (new Array(5)) code. For Arrays, we have convenient different syntax that has more consistent and predictable behavior: [5].
>
> You didn't answer my question. Furthermore, the same argument applies
> to nodelists: [mylist] works fine.

I see your point. Nevertheless, a method (such as Array.import() or Array.from()) instead of a one more special case for Array constructor would be more straightforward and intuitive since the method would do one exact unambiguous action.

And while it'd anyway nice to have an Array's method for importing array-like objects, I'm still convinced that having toArray() method for DOM list-objects would be very useful and more readable in many situations. For example:

	Array.from(document.querySelector('.some DIV'));

is less easy-readable than:

	document.querySelector('.some DIV').toArray();

or with asArray property instead of toArray() method:

	document.querySelector('.some DIV').asArray;

The less nested things and adjoining brackets are in code, the more readable the code is.

And again, since it's DOM's fault that we have a "special unusable type" of Array for DOM lists, it's logical to resolve the issue on side of DOM standard itself anyway (regardless of whether ECMA's Array will have from() or import() method).

Thanks.
Received on Monday, 26 December 2011 23:21:36 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Friday, 22 June 2012 06:14:09 GMT