Reason for different execution order of the mapping fn in `Array.from` and `TypedArray.from`?

I was reading the %TypedArray%.from spec and I noticed that it works differently from Array.from: it first fully iterates its iterable argument, and then it maps every value.

The difference can be observed with this code:

function* generate() {
  for (let i=0;i<3;i++) {
    console.log(`Generate ${i}`);
    yield i;
  }
}

function map(v) {
  console.log(`Map ${v}`);
  return v;
}

console.log("Array.from");
Array.from(generate(), map);

console.log("%TypedArray%.from");
Uint8Array.from(generate(), map);

It will produce this output:

Array.from
Generate 0
Map 0
Generate 1
Map 1
Generate 2
Map 2

%TypedArray%.from
Generate 0
Generate 1
Generate 2
Map 0
Map 1
Map 2

I tried looking at older versions of the spec to see why they work differently, but this difference was already in the July 15, 2013 ES6 draft (which is the draft introducing %TypedArray%.from and iterables support in Array.from).

Does anyone know what is the reason behind this difference, or if there isn't a reason?

3 Likes

I brought this up in committee:
https://github.com/tc39/notes/blob/8711614630f631cb51dfb803caa087bedfc051a3/meetings/2019-07/july-23.md#inconsistency-between-arrayfrom-and-typedarrayfrom

As I recall, there wasn’t a strong reason for it, and it “should” have been addressed as part of ES6, but absent a compelling performance story to change it, nobody had any interest in doing so.

1 Like

Thanks for the link!