Array、Map などの組み込みクラスも拡張可能です。
たとえば、ここではPowerArray
ネイティブArray
から継承しています。
// メソッドをもう 1 つ追加します (さらに実行できます) class PowerArray extends Array { isEmpty() { this.length === 0 を返します。 } } let arr = new PowerArray(1, 2, 5, 10, 50); アラート(arr.isEmpty()); // 間違い let filteredArr = arr.filter(item => item >= 10); アラート(フィルターされたArr); // 10、50 アラート(filteredArr.isEmpty()); // 間違い
非常に興味深いことに注意してください。 filter
、 map
などの組み込みメソッドは、継承されたPowerArray
型とまったく同じ新しいオブジェクトを返します。内部実装では、そのためにオブジェクトのconstructor
プロパティを使用します。
上の例では、
arr.constructor === PowerArray
arr.filter()
が呼び出されると、基本的なArray
ではなくarr.constructor
正確に使用して、結果の新しい配列が内部的に作成されます。これは、結果に対してさらにPowerArray
メソッドを使用し続けることができるため、実際には非常に優れています。
さらに、その動作をカスタマイズすることもできます。
特別な静的ゲッターSymbol.species
クラスに追加できます。存在する場合は、JavaScript がmap
やfilter
などで新しいエンティティを作成するために内部で使用するコンストラクターを返す必要があります。
map
やfilter
などの組み込みメソッドで通常の配列を返したい場合は、次のようにSymbol.species
でArray
を返すことができます。
class PowerArray extends Array { isEmpty() { this.length === 0 を返します。 } // 組み込みメソッドはこれをコンストラクターとして使用します static get [Symbol.species]() { 配列を返します。 } } let arr = new PowerArray(1, 2, 5, 10, 50); アラート(arr.isEmpty()); // 間違い // フィルターはコンストラクターとして arr.constructor[Symbol.species] を使用して新しい配列を作成します let filteredArr = arr.filter(item => item >= 10); // filteredArr は PowerArray ではなく Array です アラート(filteredArr.isEmpty()); // エラー: filteredArr.isEmpty は関数ではありません
ご覧のとおり、 .filter
Array
返すようになりました。したがって、拡張機能はそれ以上渡されません。
他のコレクションも同様に機能します
Map
やSet
などの他のコレクションも同様に機能します。 Symbol.species
も使用します。
組み込みオブジェクトには、 Object.keys
、 Array.isArray
などの独自の静的メソッドがあります。
すでにご存知のとおり、ネイティブ クラスは相互に拡張します。たとえば、 Array
Object
拡張します。
通常、あるクラスが別のクラスを拡張すると、静的メソッドと非静的メソッドの両方が継承されます。これについては、「静的プロパティとメソッド」の記事で詳しく説明されています。
ただし、組み込みクラスは例外です。これらは相互に静的情報を継承しません。
たとえば、 Array
とDate
どちらもObject
から継承するため、それらのインスタンスにはObject.prototype
のメソッドがあります。ただし、 Array.[[Prototype]]
Object
を参照しないため、たとえばArray.keys()
(またはDate.keys()
) の静的メソッドはありません。
Date
とObject
のピクチャ構造は次のとおりです。
ご覧のとおり、 Date
とObject
の間にリンクはありません。これらは独立しており、 Date.prototype
のみがObject.prototype
から継承します。
これは、 extends
で得られるものと比較した、組み込みオブジェクト間の継承の重要な違いです。