简体   繁体   English

`map()`的奇怪行为

[英]Weird behavior of `map()`

AS: Variable names were changed for simplicity. AS:为简单起见,更改了变量名称。

My goal is to create new array-like class, every instance of which will have seven numbers, based on whatever quantity of whatever arguments. 我的目标是创建一个类似于数组的新类,每个实例都有七个数字,基于任何参数的数量。

So, the code is something like this: 所以,代码是这样的:

"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)));
    }
}

It works fine, so new SevenNumbers(); 它工作正常,所以new SevenNumbers(); returns array of seven numbers, either default (0), or not. 返回七个数字的数组,默认(0)或不是。
The debugger -part is important: it tells us about getting into constructor of a SevenNumbers class. debugger -part很重要:它告诉我们如何进入SevenNumbers类的构造函数。

The problem emerges when I try to map() gotten object. 当我尝试map()对象时出现问题。
Try the following code: 请尝试以下代码:

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].

First part works in predicted way, but at the 3rd line we're getting in the constructor again! 第一部分以预测的方式工作,但在第3行我们再次进入构造函数!
The most confusing thing is that the only argument here is the length of arr . 最令人困惑的是,这里唯一的论点是arr的长度。 Why the length? 为什么长度?

Although the final result is correct, this weird behavior interferes with my work in practice, since there are additional calculations in between. 尽管最终结果是正确的,但这种奇怪的行为会干扰我在实践中的工作,因为它们之间还有其他的计算方法。

What is wrong here? 这有什么不对? Why doesn't it just take values from ready custom array, why create new one? 为什么不从现成的自定义数组中获取值,为什么要创建新的?

That's because map uses ArraySpeciesCreate to create an array like the original one. 那是因为map使用ArraySpeciesCreate来创建一个类似于原始数组的数组。

If this didn't happen, at the end you would get a normal Array instead of a SevenNumbers instance. 如果没有发生这种情况,最后你会获得一个普通的Array而不是SevenNumbers实例。

Therefore, your constructor is called in order to construct the new array which will be filled using the callback function and the items of the original instance. 因此,调用构造函数以构造将使用回调函数和原始实例的项填充的新数组。

If you don't want it, you can use Symbol.species to make map call Array instead of 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(_ => _); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM