Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
99
Help us understand the problem. What is going on with this article?
@ConquestArrow

ES6ではデータのプロパティをクラス直下で定義できない

More than 5 years have passed since last update.

TypeScriptでクラス定数をプロパティとして定義できない件を記事にした。

理由としてはおそらくECMAScript由来の仕様だろうと思い調べてみたところ、 ES6(ES2015)では定数に限らずデータのプロパティをクラスのブロック直下に定義できない ことがわかった。

babelでテスト
class Test{
    prop = 1;   //error! Unexpected token (2:6)
}

ES6でのデータのプロパティの持たせ方

仕様ではクラス直下の本体部分で定義できるのはメソッドのみでデータを保持する変数や定数は定義できない。

ClassBody[Yield] :
    ClassElementList[?Yield]
ClassElementList[Yield] :
    ClassElement[?Yield]
    ClassElementList[?Yield] ClassElement[?Yield]
ClassElement[Yield] :
    MethodDefinition[?Yield]
    static MethodDefinition[?Yield]
    ;

データのクラスプロパティ自体が持てない訳ではなく、メソッドの内部でthis.prop = 1;のように定義するか、クラスのインスタンスに後からプロパティをくっつける事で出来る。

持たせ方
class Test{
    constructor(){
        this.prop = 1;  //ok
    }
}
var a = new Test();
console.log(a.prop);    //1

a.prop2 = "str";
console.log(a.prop2); //str

クラス定数も出来ない事は無い。

クラス定数っぽいもの
class Test{
    constructor(){
    }

    get MAX(){
      return 10000;
    }
}
var a = new Test();
console.log(a.MAX); //10000
a.MAX = 0;  //error! 代入不可

TypeScriptでは

TypeScriptではクラスのデータプロパティをクラスの直下で定義できる。さらに、public/private/protected等のアクセス修飾子でアクセスの制御もできる。

OOPをやるならカプセル化のためにアクセス制御が必要なのでECMAScript側の仕様が固まる前に実装しているのだろう1。まあ、普通。

TypeScript
class Test{
    prop = 1;   //ok
    static prop2 = 3;   //ok
    private prop3 = 1;  //ok
    protected prop4 = 1;    //ok
}
class Test2 extends Test{
    get prop5(){
        return this.prop4;
    }
}
var a = new Test();
console.log(a.prop);    //1
console.log(Test.prop2);    //3
console.log(a.prop3);   //error!
console.log(a.prop4);   //error!
var b = new Test2();
console.log(b.prop4);   //error!
console.log(b.prop5);   //1

Babelでは

experimentalフラグをONにすればいける。ES.nextで仕様検討中のため。

class Test{
    prop = 1;   //ok, experimental on
}

なお、フラグをONにしなくても、値を代入しない定義だけならエラーにならなかった。これがES6の仕様に即しているのかはわからない。

babelでエラーにならないけど合ってる?
class Test{
    prop;
}

以下、愚痴。何が問題なのか。

  • this.propで宣言するのはインデントが一つ深いのでパッと見理解しにくい
    • 同一スコープなんだから、同じインデントにしようよ
  • 他のクラスベースの言語に合わせようよ
    • 使いにくいオリジナリティとか要らないから
  • クラスレベルのスコープの定数が定義しにくい
    • ただでさえスコープ制御が貧弱なんだからもう少しなんとかならなかったの?
    • Number.MAX_SAFE_INTEGERみたいなのを簡単に定義させてほしい
  • アンチパターンとしてクラスプロパティの宣言時に値を入れておきたくないというのはわかる
    • staticなプロパティや定数までできなくしたのはやり過ぎじゃ?
    • そのくせ宣言後のクラスインスタンスにプロパティ生やせちゃうのは…どうにかならなかったん?
  • IDEの補完にむいてなさそう
    • 最近の各IDEの補完は賢いからこれは杞憂に終わるかも
  • ES.nextー!早く来てくれー!

  1. ただ何故かクラス定数は簡単に定義できない。 

99
Help us understand the problem. What is going on with this article?
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
ConquestArrow
ノンプログラマです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
99
Help us understand the problem. What is going on with this article?