为什么Array.from不以与Array.Prototype.map相同的方式调用回调?

2022-02-26 00:00:00 mapping callback javascript ecmascript-6

撰写时MDN's description of the Array.from function状态:

Array.from()有一个可选参数mapFn,该参数允许您对正在创建的数组的每个元素执行map()函数。

更清楚,Array.from(obj, mapFn, thisArg)
结果与Array.from(obj).map(mapFn, thisArg)
相同 只是它不创建中间数组。

但是,它不具有完全相同的行为,如下所示:

function mapFn(...args) {
    console.log(...args);
}

let obj = { 0: "value", length: 1 };
let thisArg = { };

Array.from(obj, mapFn, thisArg);
Array.from(obj).map(mapFn, thisArg);

Array.from不向回调传递第三个参数。

这与Array.from上的ECMAScript 2020规范一致:

Call(mapfn,thisArg,«nextValue,k»)。

而对于Array.prototype.map,规范具有:

Call(callbackfn,thisArg,«kValue,k,O»)。

显然,以上引用自MDN并不完全正确。

问题

为什么会有这样的差异?让Array.from像上面引用的MDN中所述的map()函数那样工作不是更有意义吗?

mdn

mdn中的引用几乎完全正确。


解决方案

mdn引用几乎完全正确。但它也是不完整的。

几乎不正确:

它允许您执行map()函数

它不会执行本机.map()方法。它执行的映射操作几乎与相同。

未完成

更清楚,Array.from(obj, mapFn, thisArg)
结果与Array.from(obj).map(mapFn, thisArg)
相同 只是它不创建中间数组。

在为True时,只要未使用.map()的第三个参数,也应包括";。";以绝对100%匹配事物的工作方式。

为什么会有这样的差异?让Array.from像上面引用的MDN中所述的map()函数那样工作不是更有意义吗?

问题很有趣,但答案实际上很无聊。因为您可以在非数组上使用Array.from()

这有什么关系?您显示了一个类似数组的映射。类似数组的整体存在于中,可以作为第三个参数进行传递。实际上是通过.map()

实现的
function mapFn(...args) {
    console.log(this, ...args);
//              ^^^^^ also log this for clarity
}

let obj = { 0: "value", length: 1 };
let thisArg = { this: "arg" };

Array.prototype.map.call(obj, mapFn, thisArg);

但是,如果整个值不存在,则情况并非如此,如使用迭代器:

function* example() {
  yield 1;
  yield 2;
  yield 3;
  if (Math.random() < 0.5) //make the iterator result uncertain
    yield 4;
}

function mapFn(...args) {
    console.log(...args);
}

Array.from(example(), mapFn)

每次调用映射回调时,它只知道当前现有值。迭代器还没有物化,所以您不仅不能获得它的完整视图,而且是Array.from()将其转换为物化视图。这是一个先有鸡还是先有蛋的问题。

相关文章