I am reading You Don't Know JS: ES6 & Beyond and I encountered this snippet in Symbol.species section.
class Cool {
// defer `@@species` to derived constructor
static get [Symbol.species]() { return this; }
again() {
return new this.constructor[Symbol.species]();
}
}
class Fun extends Cool {}
class Awesome extends Cool {
// force `@@species` to be parent constructor
static get [Symbol.species]() { return Cool; }
}
var a = new Fun(),
b = new Awesome(),
c = a.again(),
d = b.again();
c instanceof Fun; // true
d instanceof Awesome; // false
d instanceof Cool; // true
It seems like the function Symbol.species{ return Something } should always return a constructor function. But in the first presence of this function:
static get [Symbol.species]() { return this; }
I am confused because I always think this should be an object instead of a constructor function.
Could you please help me to clarify the facts?
And about return new this.constructor[Symbol.species]();
, what does this here refer to?
Definition of snippet : a small part, piece, or thing especially : a brief quotable passage.
a small and often interesting piece of news, information, or conversation: I heard an interesting snippet on the radio this morning. I love listening to snippets of conversation in restaurants.
(1) He passed on any interesting snippets of information he could glean from his colleagues. (2) I heard an interesting snippet on the radio this morning. (3) I love listening to snippets of conversation in restaurants. (4) Have you got any interesting snippets for me?
Snippets are short, reusable text blocks that can be used on contact, company, deal and ticket records, in email templates, in chat conversations, and when logging an activity or note. If you want to create reusable emails, learn more about the templates tool.
this
will refer to something different inside a method depending on the context it was executed.
In class methods, static methods, this
will refer to the class.
So for instance with
static get [Symbol.species]() { return this; }
Since this is a class method, it will is executed on the class and this
will refer to the class
//since this is a getter we don't use trailing `()`
Cool[Symbol.species] === Cool;
//It does not exist on instances
var myCool = new Cool();
console.log( myCool[Symbol.species] );
//will give undefined
Now for instance methods, like the again
method, they only exist on the instance and so are called from the instance and not the class:
console.log( Cool.again );
//will give undefined
var myCool = new Cool();
var newInstance = myCool.again();
In instance methods this
refers to the instance, not the class.
So given:
return new this.constructor[Symbol.species]();
this
is the instance (eg, new Cool
)this.constructor
is the constructor that created the instance (eg, Cool
)this.constructor[Symbol.species]
is the class getter method Symbol.species
new this.constructor[Symbol.species]()
is a new instance of the class that Symbol.species returnedSo the whole line is returning a new instance of a class that the static getter Symbol.species
method returns.
This allows a class to have methods that create new instances of a class without knowing its name.
So as the example shows, even though Fun
never defined it's own again
method again
knows how to create a new instance of Fun
. And as Awesome
shows you can just override Symbol.species to change what instance again
will create.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With