A.S。:为简单起见,更改了变量名称。
我的目标是创建一个类似于数组的新类,每个实例都有七个数字,基于任何参数的数量。
所以,代码是这样的:
"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
- 部分非常重要:它告诉我们如何进入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].
第一部分以预测的方式工作,但在第3行我们再次进入构造函数!
最令人困惑的是,这里唯一的论点是arr
的长度。为什么长度?
虽然最终结果是正确的,但这种奇怪的行为会干扰我在实践中的工作,因为中间还有其他计算。
这里有什么问题?为什么不从现成的自定义数组中获取值,为什么要创建新的?
答案 0 :(得分:4)
这是因为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(_ => _);