Reputation: 1919
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?
Upvotes: 6
Views: 159
Reputation: 42736
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.
Upvotes: 5