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
的长度。为什么这么长?
虽然最终结果是正确的,但这种奇怪的行为干扰了我的实践工作,因为中间有额外的计算。
这里有什么问题?为什么它不直接从现成的自定义数组中获取值,为什么要创建新数组?
最佳答案
那是因为 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(_ => _);
关于javascript - `map()` 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37648091/