javascript - `map()` 的奇怪行为

标签 javascript arrays google-chrome

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.speciesmap 调用 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/

相关文章:

javascript - 如何使用 Chart.js 显示 .xml 文件中的数据?

javascript - 在用户键入时从输入字段中删除字符(keyup)

javascript - 删除一个对象的键也会删除另一个对象中的键 - Javascript

javascript - Jasmine 单元测试 - 测试对象的未定义属性

java - 如何在java中实现将泛型类型数组转换为泛型类型二维数组的函数?

java - 如何初始化嵌套数组

c - 制作一个包含结构的数组 - C

google-chrome - GM_setValue 在哪里存储数据?

javascript - 通过浏览器Javascript API获取firefox或Chrome Tab的Process-Id

javascript - 如何在 Firefox 控制台上启用显示 Firebase 的 DocumentReference