野次馬エンジニア道

野次馬な気持ちでプログラミングをあれこれと綴ります

JavaScriptでオブジェクト指向 (5) - ECMAScript 6で

以前ES5でまとめたが、最近ES6のコードの目にする機会が急激に増えた気がする。

Babelの babeljs.ioのオンラインの変換をみながらclassの利用方法から確認してみた。

クラスの定義

以前の例をES6で書き直す

//ES6以前
var Foo = function(_name){
    this.name = _name;
}
Foo.prototype.greet = function(){
    return "hello my name is "+ this.name;
}

これが

//ES6
class Foo {
    constructor(_name) {
        this.name = _name;
    }
   greet() {
    return "hello my name is "+ this.name;
   }
}
var my = new Foo("bar");
my.greet(); // hello my name is bar.

クラスの継承

以前は、自分でプロパティを上書きしたり足したりと面倒だったが、 ES6ならextendsでスッキリと記述可能。

class SubClass extends BaseClass {
    constructor(...args){
        super(...args);
    }
    test() {
        super.test();
    }
}

親クラスへのアクセスもsuperがキーワードとして予め用意されている。宣言時につかっている...はレストパラメータといって可変長の引数を扱えるようになったもの。逆にsuper呼び出し時の配列を展開するスプレッドオペレータ。これまでの

var score = [5,1,2];
Math.max.apply(null, score);

のようなワークアランドを書かなくて済むようになる。

アクセサ・スタティックメソッド

以前見たように、ES5にはObject.defineProperty()を使ってアクセサを定義することが可能だった。 ES6では、getsetがキーワードに追加されており

class Foo
{
  constructor(name)
  {
    this._name_ = name;
  }

  get name(){
    return this._name_;
  }

  set name(name){
    this._name_ = name;
  }

  static showName(foo)
  {
    console.log(foo.name);
  }
}
var foo = new Foo("bar");
Object.getOwnPropertyDescriptor(foo.__proto__, "name").set; // function name(name) { this._name_ = name; }
Object.getOwnPropertyDescriptor(Foo.prototype, "name").get; //function name() { return this._name_; }
Foo.showName(foo); //"bar"

のようにスッキリと書ける。ついでにstaticキーワードでスタティックなメソッドも宣言可能。

その他の注意点

  • クラスの宣言は巻き上げ(Hoisted)られない。下記のような動作になる
foo(); // OK !
function foo(){}

var foo = new Foo(); //throws ReferenceError exception
class Foo{}
  • consutructorの戻り値はreturnステートメントがない場合は、新しいインスタンスが返るが、returnステートメントがある場合は何でも返せる。 Object.create(null) (null をプロトタイプとするオブジェクトを生成)を返す例で挙動を見ると
class Foo
{
  constructor()
  {
    return Object.create(null);
  }
}

new Foo() instanceof Foo //"false"

となる。