Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symbol.species example from MDN not making sense?

Tags:

javascript

I was just translating an article about Symbol.species in MDN, when I stumpled upon the following section:

You might want to return Array objects in your derived array class MyArray. For example, when using methods such as map() that return the default constructor, you want these methods to return a parent Array object, instead of the MyArray object. The species symbol lets you do this:

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 

Beside having trouble to translate the text, which didn't give me the feeling to know what's going on, the code doesn't prove their point. When I comment out the line static get [Symbol.species]() { return Array; } the result is exactly the same.

Here's my code:

"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 

And my console output:

➜ node test.js false true 

Is that article simply wrong, or am I, as a JS/Node beginner, missing an important detail?

like image 461
Flip Avatar asked Jun 28 '16 17:06

Flip


People also ask

What is symbol species in JavaScript?

The well-known symbol Symbol. species specifies a function-valued property that the constructor function uses to create derived objects.

How do I create a new symbol in ES6?

Symbols are new primitive type introduced in ES6. Symbols are completely unique identifiers. Just like their primitive counterparts (Number, String, Boolean), they can be created using the factory function Symbol() which returns a Symbol. Every time you call the factory function, a new and unique symbol is created.

How do you use symbols in JavaScript?

JavaScript symbol You can use that symbol (the random big number) as a key in objects. A symbol is created by calling the Symbol function which takes an optional argument string which is used only for debugging purposes and acts as a description of the symbol. The Symbol function returns a unique symbol value.


2 Answers

You are missing an important detail. If you subclass array, and then do a map, using Symbol.species you can get back an array, not a member of your derived class. Sometimes you want that, for instance if you are exposing an API as a library author. You may want some special subclass sauce for your internal use but expose methods that return regular arrays for public consumption.

And there's no real limit, you can set up an alternate constructor for anything at all.

As for why commenting out the line doesn't change anything, remember that subclassing built-ins is new, may not be fully and correctly implemented, and that this is especially true with node.js where if they jump on the bandwagon early they get stuck supporting something 'wrong' for years in an LTS (they got burned on that on Object.observe).

like image 64
Jared Smith Avatar answered Oct 08 '22 19:10

Jared Smith


When I comment out the line static get [Symbol.species]() { return Array; } the result is exactly the same.

In a correct implementation of ES6 it wouldn't be the same!

For anyone looking for more examples, this article from Keith Cirkel (keithamus on Github) does a lot more at exlaining the concept than the MDN docs.


And here is an excerpt (emphasis mine):

"Now, if you were to make a class Foo extends Array - every time you called Foo#map while before it would return an Array (no fun) and you’d have to write your own Map implementation just to create Foos instead of Arrays, now Foo#map return a Foo, thanks to Symbol.species"

like image 34
José Avatar answered Oct 08 '22 18:10

José