0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

初心者による ES6 class構文

0
Last updated at Posted at 2020-01-07

ES6によるclass構文の概要

javascriptにおけるclass構文は、主に「クラスの拡張」に重きを置いたものであるため、構文自体は他の言語を模倣した形となっている。つまり、「インスタンス」という概念はあるものの、いわゆる「クラス」がなく、「プロトタイプという概念」だけが存在するということである。ES6でのclassキーワードでのクラスは、関数として呼び出しは出来ないが、内部的には関数である。

sample.js
class User {
 static age = 100
 constructor(name = '') {
  this.name = name
 }
 get() {
  /*コード内容*/
 }
 set() {
  /*コード内容*/
 }
}

//インスタンスの作成
const sample_user = new User('Tanaka')

特徴的なのは、constructor(Cではコンストラクタ)である。constructorはインスタンスが作成されたときに呼び出されるため、constructor内のthisはそのインスタンスを指している。constructorメソッドはオプションであり、クラスのインスタンスに対して、初期設定を行う。

またインスタンスの作成方法は、newキーワードを使う。
newキーワードで生成したインスタンスに関して後からインスタンスを追加することもでき、このことから他言語のクラスとは違うことがわかる。

classにおけるthisとbind

thisキーワードは、コンストラクターによって生成されるインスタンスを表すものである。thisキーワードはどこからでも参照できる特別な変数であるがよえに、呼び出す場所、呼び出しの方法によって中身が変わってきてしまう。
そして、class内のメソッドは、自動的にバインドがされない。バインドされないとは、あるメソッドを呼び出したときにそれがどこのclassで定義されているメソッドなのかがわからないという仕様である。例えば、

sample.js
class app {
 get() {
  const nameList = /*urlからnameのリストをダウンロードする*/
  return nameList.map(function(name) {
    return this.set(name)
  })
 }
 set(name) {
  this.name = name + ''
 }
}

一見よさそうに見えるが、getメソッドが呼び出したsetメソッド内のthisはもうそのインスタンスを指していないため、nameは正しく保存されない。
このことを解決する手段は何種類かある。
一つ目は、constructorでバインドしてしまうことだ。

sample.js
class app {
 constructor(name = '') {
  this.name = name
  this.set = this.set.bind(this)
 }
 get() {
  const nameList = /*urlからnameのリストをダウンロードする*/
  return nameList.map(function(name) {
    return this.set(name)
  })
 }
 set(name) {
  this.name = name + ''
 }
}

constructorでbind(this)を用いることで、setを呼び出したインスタンスとset内で用いられているthisを同じインスタンスにしている。C言語でいうところのポインタを同じにするということだ。
二つ目はthatをかませることだ。

sample.js
class app {
 constructor(name = ''){
  this.name = name
 }
 get() {
  const that = this
  const nameList = /*urlからnameのリストをダウンロードする*/
  return nameList.map(function(name) {
    return that.set(name)
  })
 }
 set(name) {
  this.name = name + ''
 }
}

もしくは

sample.js
 get() {
  const nameList = /*urlからnameのリストをダウンロードする*/
  return nameList.map(function(name) {
    return this.set(name)
  }, this)
 }

thatをいちいち作るとかっこ悪いのでmapの二つ目の変数にオプションとして付け加えるという方法もある。

しかし、一番使われているのはアロー関数を用いる解決策ではないだろうか。
アロー関数のthisはアロー関数が定義されたthisにバインドされる。

sample.js
 get() {
  const nameList = /*urlからnameのリストをダウンロードする*/
  return nameList.map((name) => this.set(name))
 }

このthisはそれぞれのnameに対して適切に行われる。

classの拡張

javascriptでclassを継承するときに覚えておくべきことは、やはりclassは親のプロパティを継承することである

sample.js
class Student extends Person {
 constructor(name, age, score) {
  super(name, age)
  this.score = score
 }
}

javascriptではentendsキーワードを用いて、継承を行う。superキーワードを使うことで、いちいち親のコンストラクタをもう一度呼び出さなくてもよい。また、superキーワードは親のメソッドを呼び出したいときにも使われる。

参考資料

山田祥寛様 「javascript本格入門」
JD Isaacks様 「入門javaScriptプログラミング」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?