Javascript Symbol.MDN中的物种示例没有意义?
我刚翻译了一篇关于MDN的文章,就在这时我遇到了以下部分: 您可能希望返回派生数组类MyArray中的数组对象。例如,当使用诸如map()之类返回默认构造函数的方法时,您希望这些方法返回父数组对象,而不是MyArray对象。使用“物种”符号可以执行以下操作: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
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中重写它