Javascript Symbol.MDN中的物种示例没有意义?

Javascript Symbol.MDN中的物种示例没有意义?,javascript,Javascript,我刚翻译了一篇关于MDN的文章,就在这时我遇到了以下部分: 您可能希望返回派生数组类MyArray中的数组对象。例如,当使用诸如map()之类返回默认构造函数的方法时,您希望这些方法返回父数组对象,而不是MyArray对象。使用“物种”符号可以执行以下操作: class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { r

我刚翻译了一篇关于MDN的文章,就在这时我遇到了以下部分:

您可能希望返回派生数组类MyArray中的数组对象。例如,当使用诸如map()之类返回默认构造函数的方法时,您希望这些方法返回父数组对象,而不是MyArray对象。使用“物种”符号可以执行以下操作:

class MyArray extends Array {
  // Overwrite species to the parent Array constructor
  static get [Symbol.species]() { return Array; }
  }
var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array);   // true
除了翻译文本有困难之外,代码并不能证明他们的观点,这并没有给我一种知道发生了什么的感觉。当我注释掉行
static get[Symbol.species](){return Array;}
时,结果完全相同

这是我的密码:

"use strict";

class MyArray extends Array {
  // Overwrite species to the parent Array constructor
  // static get [Symbol.species]() { return Array; }
}
var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);

console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array);   // true
和我的控制台输出:

➜ node test.js
false
true

那篇文章是完全错误的,还是作为一名JS/Node初学者,我遗漏了一个重要的细节?

您遗漏了一个重要的细节。如果您对数组进行子类化,然后使用Symbol.species进行
映射,则可以返回数组,而不是派生类的成员。有时,您需要这样做,例如,如果您以库作者的身份公开API。您可能需要一些特殊的子类sauce供内部使用,但需要公开返回正则数组供公众使用的方法

而且没有真正的限制,你可以为任何东西设置一个替代构造函数


至于为什么注释掉这一行不会改变任何事情,请记住,子类化内置是新的,可能没有完全正确地实现,尤其是node.js,如果他们很早就加入这一行列,他们会在LTS中支持“错误”多年(他们在这一点上被烧掉了).

您缺少一个重要的细节。如果您对数组进行子类化,然后使用Symbol.species进行
映射,则可以返回数组,而不是派生类的成员。有时,您需要这样做,例如,如果您以库作者的身份公开API。您可能需要一些特殊的子类sauce供内部使用,但需要公开返回正则数组供公众使用的方法

而且没有真正的限制,你可以为任何东西设置一个替代构造函数

至于为什么注释掉这一行不会改变什么,请记住,子类化内置是新的,可能没有完全正确地实现,尤其是node.js更是如此,如果他们很早就加入这一行列,他们会在LTS中多年坚持支持“错误”的东西(他们在这一点上被烧掉了)

当我注释掉行
static get[Symbol.species](){return Array;}
时,结果完全相同

在ES6的正确实现中,情况就不一样了

对于任何想要寻找更多例子的人来说,Keith Cirkel(keithamus on)在阐述这个概念方面比MDN文档做了更多


下面是一段摘录(我的重点):

“现在,如果你要制作一个
类Foo扩展数组
——每次调用
Foo#map
,在它返回数组之前(没有乐趣)您必须编写自己的Map实现才能创建
Foo
s而不是
Array
s,现在
Foo\Map
返回
Foo
,这要感谢
Symbol.species

当我注释掉行
static get[Symbol.species](){return Array;}
时,结果完全相同

在ES6的正确实现中,情况就不一样了

对于任何想要寻找更多例子的人来说,Keith Cirkel(keithamus on)在阐述这个概念方面比MDN文档做了更多


下面是一段摘录(我的重点):

“现在,如果你要制作一个
类Foo扩展数组
——每次调用
Foo#map
,在它返回数组之前(没有乐趣)您必须编写自己的Map实现才能创建
Foo
s而不是
Array
s,现在
Foo\Map
返回
Foo
,这要感谢
Symbol.species


对不起,我真的不明白。假设我们想用
map
生成MyArray对象,我该怎么做?我一定会继续挖掘,以确保我能判断您的答案是否正确…@Flip返回您的子类是默认设置,即
myArray.map(someFn)
将返回myArray的实例。有时,您可能会希望覆盖它(如我上面给出的library author示例)。这对于主机实现的方法(如
Array.prototype.map
)更为重要,对于自定义方法,您只需在子类中重写它。但是,符号(物种)可以(理论上)获得C++中的代码提速> map >代码,而不是JavaScript。好的,我将阅读主机实现方法和自定义方法之间的区别,并接受您的答案。谢谢你和我在一起@没问题。至于“主机实现的”方法,我只是指JavaScript提供的现成方法,而不是您编写的方法。它们不一定在JS中实现,它们经常以(更快)的宿主语言来实现,对于大多数JavaScript引擎来说,它们是C++。请记住,JS运行在像V8这样的虚拟机上,它不会直接编译成本机代码。对不起,我真的不明白。假设我们想用
map
生成MyArray对象,我该怎么做?我一定会继续挖掘,以确保我能判断您的答案是否正确…@Flip返回您的子类是默认设置,即
myArray.map(someFn)
将返回myArray的实例。有时,您可能会希望覆盖它(如我上面给出的library author示例)。这对于主机实现的方法(如
Array.prototype.map
)更为重要,对于自定义方法,您只需在su中重写它