2016-05-22 16 views
5

私はあなたが知らないJSを読んでいます:ES6 &これを超えて、このスニペットがSymbol.speciesセクションで発生しました。このスニペットでは何が行われますか?

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

機能Symbol.speciesは{何かを返す}常にコンストラクタ関数を返す必要がありますように思えます。しかし、この関数の最初の存在で: static get [Symbol.species]() { return this; } 私はいつもこれがコンストラクタ関数の代わりにオブジェクトであるべきだと思うので、私は混乱しています。 事実を明確にするために私を助けてください。

return new this.constructor[Symbol.species]();とは何ですか?

答えて

5

thisは、実行されたコンテキストに応じてメソッド内で異なるものを参照します。

クラスメソッドでは、静的メソッドthisがそのクラスを参照します。

static get [Symbol.species]() { return this; } 

と例えばだから

このクラスのメソッドであるため、それはクラス上で実行され、thisのようなインスタンスメソッドのために今のクラスに

//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 

を参照しますagainメソッドでは、インスタンス上にのみ存在するため、クラスではなくインスタンスから呼び出されます。

console.log(Cool.again); 
//will give undefined 
var myCool = new Cool(); 
var newInstance = myCool.again(); 

インスタンスメソッドでは、thisはクラスではなくインスタンスを参照します。

だから、与えられた:

return new this.constructor[Symbol.species](); 
  • thisがインスタンスである(例えば、new Cool
  • this.constructorは、インスタンスを作成し、コンストラクタ(例えば、Cool)である
  • this.constructor[Symbol.species]は、クラスのgetterメソッドでありますSymbol.species
  • new this.constructor[Symbol.species]()は、 Symbol.speciesが返したクラス

したがって、スタティックゲッターSymbol.speciesメソッドが返すクラスの新しいインスタンスが返されます。

これにより、クラスの名前を知らなくてもクラスの新しいインスタンスを作成するメソッドをクラスに持たせることができます。

だから、例が示すように、たとえFunFunの新しいインスタンスを作成する方法を知っているagainそれ自身againメソッドを定義したことはありません。 Awesomeに示すように、Symbol.speciesをオーバーライドして、againのインスタンスを変更することができます。