Help us understand the problem. What is going on with this article?

ES2015(ES6)の子クラスの constructor() では super() が必須で、super()の前には this.* や super.* が使えない話

More than 3 years have passed since last update.

TL;DR

タイトルのままです。

背景:よく出会うエラー

  1. SyntaxError: missing super() call in constructor
  2. SyntaxError: 'this' is not allowed before super()
  3. SyntaxError: 'super.*' is not allowed before super()

1. 子クラスのconstructor()ではsuper()呼び出しが必須

エラーになるコード例

こういうコードはエラーになります。

missing-super-error.js
class Parent {
}

class Child extends Parent {
  constructor() {}
}

解決・解消コード例

super()を追加します。

fix-missing-super-error.js
class Parent {
}

class Child extends Parent {
  constructor() { super(); }
}

または特にコンストラクタで何もしないなら、constructor()自体を削除してしまいましょう。

fix-missing-super-error.js
class Parent {
}

class Child extends Parent {
}

これは、デフォルトで以下のように書いたのと同じです。

default-subclass-constructor.js
class Child extends Parent {
  constructor(...args) { super(...args); }
}

ちなみにこのコードは、new Child()したときの引数をそのまま親クラスのコンストラクタへ引数として渡します。

2. 子クラスのconstructor()ではsuper()の前でthisを参照することはできない

エラーになるコード例

こういうコードは、どの子クラス定義でもエラーになります。

this-before-super-error.js
class Parent {}

class Child01 extends Parent {
  constructor(params) {
    // super()の前で自プロパティへ代入
    this.params = params;
    super();
  }
}

class Child02 extends Parent {
  constructor(params) {
    // super()の前で自クラスのメソッドを呼ぶ
    const processed_params = this.preprocessing(params);
    super(processed_params);
  }

  preprocessing(params) {
    // process something
  }
}

解決・解消コード例

基本的にはsuper()呼び出しより後にthis.*を移動させると良いでしょう。

fix-this-before-supper-error.js
class Child01 extends Parent {
  constructor(params) {
    super();
    this.params = params;
  }
}

Child02クラスのように、自クラスのメソッドの結果をsuper()に渡している場合は前後入れ換えで解決しませんが、このようなケースではクラス設計に間違いがある場合がほとんどです。

fix-this-before-supper-error.js
class Child02 extends Parent {
  constructor(params) {
    super(params);
    this.preprocessing();
  }
}

上記のように引数をそのまま渡してsuper()を呼び、その後に自インスタンスを加工するという順番にできないか検討してみましょう。

ちなみに、super()の戻り値と、super()の後で参照できるthisは同じものです。

compare-instance-with-this.js
class Parent {}

class Child02 extends Parent {
  constructor() {
    const instance = super();
    console.log(instance === this); // => true
  }
}

new Child02();

3. 子クラスのconstructor()ではsuper()の前でsuper.*(親クラス呼び出し)はできない

エラーになるコード例

こういうコードは、どの子クラス定義でもエラーになります。

super-before-super-error.js
class Parent {
  processing(params) {
    // process something
  }
  get name() { return 'NAME'; }
}

class Child01 extends Parent {
  constructor(params) {
    // 親クラスのプロパティを参照する
    const name = super.name + params;
    super();
  }
}

class Child02 extends Parent {
  constructor(params) {
    // 親クラスのメソッドを呼ぶ
    const processed_params = super.processing(params);
    super(processed_params);
  }
}

解決・解消コード例

これらもthisのときと同様、基本的にはsuper()を先に呼ぶようにします。

fix-super-before-super-error.js
class Child01 extends Parent {
  constructor(params) {
    super();
    const name = super.name + params;
  }
}

Child02のように親クラスのメソッドの実行結果をsuper()の引数として渡している場合は、thisのときと同じようにクラス設計を見直して、親クラスのconstructor()の方にprocessing()実行を移動させてしまうのが良いでしょう。

fix-super-before-super-error.js
class Parent {
  constructor(params) {
    this.processed_params = this.processing(params);
  }
  processing(params) {
    // process something
  }
}

class Child02 extends Parent {
  constructor(params) {
    super(params);
    this.processed_params
  }
}

以上です。役に立ちそうでしたら「ストック」してもらえると嬉しいです。
それでは、良いES6ライフをお過ごしください。

noriaki
仕事はマーケターなので基本的にコードは書いてません。Qiitaへの投稿は個人の趣味としての開発に関係するものです。したがって、特に明示しない限り所属する企業や団体には一切関係ありません。
http://blog.noriaki.me
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした