ES 6のクラスの書き方と継承


JS言語では、インスタンスオブジェクトを生成する従来の方法は、構造関数によって行われる。コンストラクタの一例は以下のコードです。
  function Point(x, y) {
  this.x = x;
  this.y = y;}

  Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';};

  var p = new Point(1, 2);
このような書き方は伝統的な対象言語(例えばC++とJava)とは大きく違っています。この言語を新しく勉強したプログラマーはすぐに困惑してしまいます。ES 6は伝統的な言語に近い書き方を提供し、クラスという概念を導入し、対象とするテンプレートを提供しています。クラスのキーワードでクラスを定義できます。基本的に、ES 6のクラスは文法飴だけと見なしてもいいです。ほとんどの機能はES 5でできます。新しいクラスの書き方は対象の原型の書き方をはっきりさせ、対象に向かってプログラミングする文法のようにしか見えません。上のコードはES 6のクラスで書き換えます。次のようになります。
//   
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}

toString() {
return '(' + this.x + ', ' + this.y + ')';
}}
上のコードは「クラス」を定義しています。中には構造方法があります。つまり、ES 5の構造関数Pointは、ES 6のPoint類に対応した構造方法である。point類は構造方法の他に、toString方法も定義されています。ただし、「クラス」を定義する方法は、前にFunctionというキーワードを追加する必要がなく、直接関数定義を入れてもいいです。また、方法間にはカンマ区切りは不要です。
//hasOwnProperty                 
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
ES 6のクラスは、構造関数の別の書き方として考えられます。
class Point {
// ...
}

typeof Point // "function"
上のコードからは、クラスのデータの種類が関数であり、クラス自体が構造関数を指していることが分かります。クラスの属性名は、表式を使用することができます。
let methodName = 'getArea';

class Square {
 constructor(length) {
 // ...
 }

[methodName]() {
// ...
}}
上記のコードでは、スクウェア類のメソッド名getAreaは、表現から得られます。
クラス内ではデフォルトは厳しいモードですので、use strictを使って運転モードを指定する必要はありません。あなたのコードがクラスやモジュールに書いてある限り、厳格なモードだけが利用できます。
将来のすべてのコードを考慮して、実はモジュールの中で実行しています。だから、ES 6は実際に言語全体を厳格なモードにアップグレードしました。
constructorの方法
constructorメソッドは、カテゴリのデフォルトの方法であり、newコマンドによりオブジェクトインスタンスを生成する場合、自動的に起動します。一つの種類にはconstructorの方法が必要で、明示的な定義がないと、空きのconstructorの方法がデフォルトで追加されます。
class Point {}
//    
class Point {
constructor() {}}
上のコードでは、空のクラスPointを定義しています。JSエンジンは自動的に空のconstructor方法を追加します。constructor方法は、デフォルトではインスタンスオブジェクト(すなわちthis)を返します。クラスはnewで呼び出さなければなりません。そうでないとエラーが発生します。これは普通のコンストラクタとの主な違いです。後者はnewを使わずに実行できます。
class Foo {
   constructor() {

}}

Foo()
// TypeError: Class constructor Foo cannot be invoked without 'new'
クラスのインスタンスオブジェクトの書き方は、ES 5と全く同じで、newコマンドを使用しています。前に述べましたが、newをかけるのを忘れたら、関数のようにクラスを呼び出すと、エラーが発生します。
class Point {
// ...
}
//   
var point = Point(2, 3);
//   
var point = new Point(2, 3);
クラスには変数が存在しません。この点はES 5とは全く違います。
new Foo(); // ReferenceError
class Foo {}
クラスの方法
staticキーワードを加えると、この方法がインスタンスに引き継がれないことを表し、直接クラスによって呼び出されることを「静的方法」といいます。
class Foo {
     static classMethod() {
     return 'hello';
     }
}

Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
上のコードからは、FooクラスのクラスのclassMethodメソッドの前にstaticキーワードがあり、この方法は、Fooクラスで直接呼び出すことができる静的な方法であることを示しています。例で静的方法を呼び出すと、エラーが発生し、方法が存在しないことを表します。
クラスを引き継ぐクラスは、ES 5のプロトタイプチェーンを修正することによって引き継ぐことができます。クリアで便利です。
class Point {}

class ColorPoint extends Point {}
上のコードは、extendsキーを通じて、Pointクラスのすべての属性と方法を継承するColorPointクラスを定義しています。しかし、コードが配置されていないため、これらの2つのクラスは全く同じで、Pointクラスをコピーしたものと同じです。コードをColorPointの内部に追加します。
class ColorPoint extends Point {
   constructor(x, y, color) {
   super(x, y); //      constructor(x, y)
   this.color = color;
   }

   toString() {
   return this.color + ' ' + super.toString(); //      toString()
   }
}
上のコードの中で、constructor方法とtostring方法の中にsuperキーワードが現れています。ここでは父の種類の構造関数を表して、父の種類のthisオブジェクトを新規作成します。ES 6もまた、サブクラスの構造関数は一回のsuper関数を実行しなければならないと要求しています。サブクラスはconstructorメソッドでsuperメソッドを呼び出す必要があります。そうでないと、新しいインスタンスを作成する時にエラーが発生します。これは、サブクラスの自分のthisオブジェクトは、父親の構造関数を介して、最初に作成し、父親と同じインスタンスの属性と方法を得て、その後、それを加工し、サブクラスの自分のインスタンスの属性と方法を加える必要があります。superメソッドを起動しないと、サブクラスはthisオブジェクトを得られません。
class Point { /* ... */ }

class ColorPoint extends Point {
    constructor() {
    }
}

let cp = new ColorPoint(); // ReferenceError
上のコードでは、ColorPointは親タイプPointを継承していますが、その構造関数はsuperメソッドを起動していません。新築のインスタンスタイムズが間違っています。
注意すべき点は、サブクラスの構造関数では、superを呼び出してから、thisキーワードを使用できます。そうでないとエラーが発生します。これは、サブクラスのインスタンスの構築は、親クラスのインスタンス加工に基づいており、super方法のみが親クラスのインスタンスに戻ることができるからである。
class Point {
   constructor(x, y) {
   this.x = x;
   this.y = y;
   }
}

class ColorPoint extends Point {
    constructor(x, y, color) {
    this.color = color; // ReferenceError
    super(x, y);
    this.color = color; //   
    }
}
上のコードの中で、サブクラスのconstructorメソッドはsuperを呼び出す前に、thisキーワードを使っていましたが、結果としてエラーが発生しました。superメソッドの後に置くのが正しいです。