Why does Array.from also take a mapFn?

Dmitry Soshnikov dmitry.soshnikov at gmail.com
Mon Jun 24 19:23:46 PDT 2013


On Mon, Jun 24, 2013 at 5:45 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

>
> On Jun 24, 2013, at 5:21 PM, Dmitry Soshnikov wrote:
>
>
> On Mon, Jun 24, 2013 at 9:31 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
>
>>
>> On Jun 24, 2013, at 8:42 AM, Jason Orendorff wrote:
>>
>> > According to the January 30 meeting notes, Array.from is getting
>> > optional map functionality.[1]
>> >
>> > This is motivated by the following example:
>> >
>> >    class V extends Array {
>> >        constructor(...args) {
>> >            super(...args);
>> >        }
>> >    }
>> >
>> >    var v, m;
>> >    v = new V(1, 2, 3);
>> >    m = v.map(val => val * 2);
>> >    console.log( m instanceof V ); // false :(
>> >
>> > Of course changing Array.from doesn't fix this; v.map() still returns
>> > an Array, same as before. And there was already an easy workaround:
>> >    m = V.from(v.map(val => val * 2));
>>
>> The issues (and discussion) is more complex then the above indicates.
>>
>> The root issue concerns what should Array producing methods such as Map
>> produce when used in an Array subclass. Should the result be an Array
>> instance (as it currently is in ES5) or should it be a new instance of the
>> subclass.  If the latter, how is the actual subclass determined.
>>
>
> If the `map` method is inherited and is called directly on the instance of
> the inherited class, then probably it's more logical to return the instance
> of the same inheriting class (i.e. the V).
>
> To answer your question how the determination of the subclass should
> happen -- first need to ask what is the [[NativeBrand]] says for "v"
> instance? Is it still "NativeArray" (shouldn't be IMO, will clarify in the
> spec later)?
>
> Can you use the [[NativeBrand]] check or at very least `constrcutor`
> property check (which though, not that safe maybe). Will it actually make
> sense to set the [[NativeBrand]] to the name of the class?
>
> if (Array.isArray(this)) {
>   var result = [];
> } else {
>   var result = new this.constructor(<somehow_get_the_default_args>?);
> }
>
> But again there is an issue with determination of the default arguments of
> the constructor, though can fallback to defaults.
>
>
> [[NativeBrand]] is long gone
>


Wow, OK, will re-read the final draft then.


>
> and regardless won't apply to all subclasses.
>
> Here is how it is currently spec'ed in Array.of and Array.from:
>
> • 1. If IsConstructor(C) is true, then
> • a. Let newObj be the result of calling the [[Construct]] internal
> method of C with an argument list containing the single item len.
> • b. Let A be ToObject(newObj).
> • 2. Else,
> • a. Let A be the result of the abstract operation ArrayCreate with
> argument len.
>
>
>
> while is pretty much equivalent to:
> class Array extends Object {
>    constructor(...args) {
>       ...
>     }
>     of(...args) {
>         let len = args.length;
>         let a;
>         if (isConstructor(this)) a = new this(len);
>         else a = new Array(len(
>         ...
>       }
> ...
> }
>
> In the spec I have a note that it would be better if there was a more
> explicitly specified way to allocate an empty collection object (of any
> kind) with a parameterized number of elements.   The current spec. for
> Array.of/from works with any constructor that treats a single numeric
> argument new call as such a request.
>

OK, thanks for the clarification. Looks reasonable. The only thing I'm
worried is those methods assume (and maybe even force) the inheriting
constructors to implement the same API as Array constructor has (that is,
either one lenght, or mupltiple entries).

OTOH, subclasses may choose different API, e.g.:

class V extends Array {
  constructor(items, config) {
    super(...items);
    this.isSparse = config.isSparse || false;
    ...
  }
}

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130624/9b75dd2d/attachment-0001.html>


More information about the es-discuss mailing list