来自MDN的Symbol.species示例没有意义?

时间:2016-06-28 17:46:57

标签: javascript

我刚刚在MDN上翻译了一篇关于Symbol.species的文章,当时我对以下部分进行了讨论:

  

您可能希望在派生数组类MyArray中返回Array对象。例如,当使用返回默认构造函数的map()等方法时,您希望这些方法返回父Array对象,而不是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的初学者,错过了一个重要的细节?

2 个答案:

答案 0 :(得分:4)

您缺少重要细节。如果您继承数组,然后使用Symbol.species执行map,则可以返回数组,而不是派生类的成员。有时您需要这样,例如,如果您将API作为库作者公开。您可能需要一些特殊的子类,以供内部使用,但是公开返回常规数组以供公共使用的方法。

并且没有实际限制,您可以为任何事情设置替代构造函数。

至于为什么注释掉该行并没有改变任何东西,请记住,子类化内置函数是新的,可能没有完全正确地实现,并且对于node.js尤其如此,如果他们跳转在早期他们被困在支持一些错误的事情上。多年来在LTS(他们在Object.observe上被烧毁了。)

答案 1 :(得分:1)

  

当我将static get [Symbol.species]() { return Array; }行注释掉时,结果是完全一样的。

在ES6的正确实现中,情况会有所不同!

对于需要更多示例的人,Keith Cirkel的this articleGithub上的 keithamus )在解释概念方面比MDN文档做得更多。


这是摘录(重点是我的):

  

“现在,如果您要创建一个class Foo extends Array-每次您调用Foo#map ,而之前它会返回一个数组(不好玩),那么您将为了编写自己的Map实现而只是创建Foo而不是Array现在Foo#map返回Foo ,这要感谢{{1 }}“