答:为简单起见,变量名称已更改。

我的目标是创建新的类似数组的类,该类的每个实例将基于任意数量的参数而具有七个数字。

因此,代码是这样的:

"use strict";
class SevenNumbers extends Array {
    constructor(...args) { debugger; // !
        // Cut the rest; fill the gaps; convert: first to object, then to primitive
        super(...Object.assign([0, 0, 0, 0, 0, 0, 0], args.slice(0, 7)).map(arg => +new Number(arg)));
    }
}

它工作正常,因此new SevenNumbers();返回由七个数字组成的数组,默认为(0),否。debugger -part很重要:它告诉我们有关SevenNumbers类的构造函数的信息。

当我尝试map()获得对象时,出现了问题。
尝试以下代码:
var arr = new SevenNumbers(8, 7, 6, 5, 4, 3, 2, 1);
// SevenNumbers [8, 7, 6, 5, 4, 3, 2] (without the last).
arr.map(_ => _);
// Array [8, 7, 6, 5, 4, 3, 2].

第一部分以预期的方式工作,但是在第三行,我们又进入了构造函数!
最令人困惑的是,这里唯一的参数是arr的长度。为什么长?

尽管最终结果是正确的,但是这种奇怪的行为在实践中干扰了我的工作,因为这之间存在其他计算。

怎么了为什么不只从准备好的自定义数组中获取值,为什么还要创建新的数组呢?

最佳答案

那是因为map使用ArraySpeciesCreate来创建一个类似于原始数组的数组。

如果没有发生,最后您将获得一个普通的Array而不是SevenNumbers实例。

因此,调用构造函数是为了构造新的数组,该数组将使用回调函数和原始实例的项目填充。

如果您不想要它,可以使用Symbol.species来使map调用Array而不是SevenNumbers

class SevenNumbers extends Array {
  constructor(...args) {
    console.log(args.toString());
    super(...Object.assign([0, 0, 0, 0, 0, 0, 0], args.slice(0, 7)).map(arg => +new Number(arg)));
  }
  static get [Symbol.species]() { return Array; }
}
new SevenNumbers(8, 7, 6, 5, 4, 3, 2, 1).map(_ => _);

09-25 19:13