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

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 UTC