Edited at

【全てのJSのオブジェクト指向嫌いマンに告ぐ】ES6のclass構文が素敵すぎて鼻水が止まらない

More than 1 year has passed since last update.


!!! 注意

この文章は偏差値の低い人間が書いてます。

・厳密な解釈を求める方

・頭の悪い人間の文章を読みたくない方

・低偏差値の人間が書いた文章を見るとデカめの蕁麻疹が全身にできるという方

は下の便利なリンクからちゃんとしたドキュメントをお読み下さい。

github Ecmascript

MDN ES6

誤りのご指摘はどんどんお待ちしております。

追記:

ES6の継承の欄が抜けてたので直しました。

JavaScriptの表記が間違ってたので直しました inoinojp さんありがとうございます

リンクの仕方を修正 Texと混ざってました  gaogao_9さんありがとうございます



「そもそもES6ってなんやねん。エントリーシートか?」

って方も多いと思います。僕も詳しくは知りません!!でも、一言で言えば、

ESは

JavaScriptのオシャンティな言い方

(ES = Ecmascriptというのは、今までバラバラでクソだったJavaScriptの仕様を少しでもマシにしようと偉い人達がまとめてくれているJavaScriptのことで、ES = JSだと思っても困んないらしいっす )

ES6は

ナウでヤングなJavaScript

ワオ!頭のわるい説明だぜ!

(JavaScriptを少しでも使いやすくするためにどんどん改良してるよーっていうことらしいです。)

新しく加わった機能を詳しく知りたい方はこういう便利なサイトがあるので読みましょう。

ES6 チートシート

もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)~


class構文について

とりあえずこのページではclass構文だけを取り扱います。


ES5まで

いままで、JSでオブジェクト指向っぽいことをしようとしたら、

prototypeチェーンとか、プロトタイプチェーンとか、ぷろとたいぷちぇーんとか、よくわからない概念と戦わなくちゃいけませんでした。


書き方

例えば、


ES5まで.js


var Animal = function (hand,foot,tail,nakigoe) {
this.hand = hand;
this.foot = foot;
this.tail = tail;
this.nakigoe = nakigoe
}

Animal.prototype.say = function () {
console.log(this.nakigoe);
}

var hamaguchi = new Animal(2,2,0,"気合だーッ!");

hamaguchi.say();
//"気合だーッ!"


とまあ、正しく書ければ良かったんですが、


間違いやすい例

僕みたいな初心者とかだと、


間違ってる.js

var Animal = function (hand,foot,tail,nakigoe) {

this.hand = hand;
this.foot = foot;
this.tail = tail;
this.nakigoe = nakigoe
}

Animal.say = function () {
console.log(this.nakigoe);
}

var hamaguchi = new Animal(2,2,0,"気合だーッ!");

//TypeError: hamaguchi.say is not a function
hamaguhi.say();


とか書いちゃったりして、意味わからんくなっちゃうものでした。ぷろとたいぷってなんやねん。しばくぞって感じです。


console.logで更に闇を垣間見る

じゃあデバッグのために変数をコンソールで表示させてみようとしても


ES5まで.js

console.log(Animal)

//{ [Function] say: [Function]}
console.log(Animal.say)
//[Function]
console.log(hamaguchi);
//{ voice: '気合' }
console.log(hamaguchi.say);
//[Function]


全部[Function]ちゃうんかい!!なんのこっちゃわからんわ!!


ES6

でもES6のclass構文が実装された今、こんなことをしなくてもシンプルにアニマル浜口が実装できるようになりました


ES6.js


class Animal {
constructor (hand,foot,tail,nakigoe) {
this.hand = hand;
this.foot = foot;
this.tail = tail;
this.nakigoe = nakigoe;

}

say (){
console.log(this.nakigoe);
}
}

var hamaguchi = new Animal(2,2,0,"気合だーッ!");

hamaguchi.say();
//"気合だーッ!"


初心者が認識できる大きな特徴は下記の3点です。


書き方がわかりやすい!!


ES5まで

今まで、このように


ES5まで

function Animal (voice){

this.voice = voice;
}
Animal.prototype.say = function () {
console.log(this.voice);
}

複数のブロック({ }のこと)に分かれて、一つのクラスを表現しなければならなかったものが、


ES6から


ES6から

class Animal{

constructor (voice){
this.voice =voice;
}
say () {
console.log(this.voice);
}
}

という大きな塊で表せるようになりました。Animalに関係するものが同じインデントに収まるのでコードの視認性がググッとアップです。

何より prototype とかいうクソ謎な呪文を唱えないですむのは非常にプラスです。

だって、 コンストラクターなんてconstructor ですからね。

まあjavaとかC++とか、そういう言語はこういう書き方しないですが、そこは一つ置いといて...rubyもinitialize()なんて言うらしいし…。JS以外書けないのでよくしりません


クラスの継承が簡単♪


ES5まで


クラスの継承

JavaScriptでは、継承のための構文は用意されていません。次のような方法で継承を行います。

プロパティの継承は、applyメソッドを呼び出す

メソッドの継承は、prototypeオブジェクトを利用する

JavaScriptでのクラス継承はなかなか複雑なので、小規模の場合は、継承を使わないようにし、大規模の場合は、ライブラリなどを使い継承を行う方が良いらしいです。

クラスプロパティとクラスメソッドの継承

JavaScriptではクラスプロパティやクラスメソッドの継承は一般的には行われません。

これは、JavaScriptではスーパークラスのクラスプロパティやクラスメソッドをサブクラスで利用するためには、それらのプロパティ定義をサブクラスにもコピーしなければならないので、コードが重複してしまうのでよくないためです。

引用元 JavaScriptの少し独特なオブジェクト指向についてまとめてみた


……。あたま弱いちゃんなのでぼくにはよくわからないです。 見ず知らずのうちに継承っぽいことをやってしまったり、わざわざライブラリを用いてやってきたということなんでしょうたぶん。


ES6から


ES6から.js

class Human extends Animal {

constructor (hand,foot,tail,nakigoe,age,place) {
super(hand,foot,tail,nakigoe);
this.age = age;
this.place = place;
}

say(){
super.say();
console.log("ワタシの年齢は" + this.age +"です。" );
}
}


めっちゃ簡単です!!!!

今まで

「クラスノ継承アルか? 食べれるアルか? ワレワレの国では机と椅子以外足が付いてるモノは何でも食べるアル」

って感じで継承を避けてきた僕にぴったりだ!

ちょっとsuper()とか新しい関数が登場しましたが、これは前のclassをそのまま呼べるよ〜〜っていう関数なので、頑張って覚えちゃいましょう。

まあ最悪これがよー分からんって方は継承を使わないって選択も全然アリだと思います。まあ今の今までまともに使えなかったものだから、存在を知っただけでも良しとしましょう。

ちなみに後述しますが、ES6のclass構文は糖衣構文なので、昔ながらの書き方も混ぜられます。

まあ死んでもprototype書きたくないけど。


ただの関数じゃないってパソコンが認識してくれる!!!

これが地味に半端ない。


ES5まで


ES5まで.js

console.log(Animal)

//{ [Function] say: [Function]}
console.log(Animal.say)
//[Function]
console.log(hamaguchi);
//{ voice: '気合' }
console.log(hamaguchi.say);
//[Function]

//まさか……
var ANIMALs = {dog:"わおん",cat:"にゃん",wotaku:"ドゥフフwww",meidaisei:"カンカンカカン、ピッピピピー"}
console.log(animals);
//{ dog: 'わおん', cat: 'にゃん', wotaku: 'ドゥフフwww' ,meidaisei:"カンカンカカン、ピッピピピー"}


……。はい。JavaScriptは全部がオブジェクトだ!なんてよく聞きますけど、function(){}由来の変数も、{}由来の変数も一緒くたにされたら、ノータリンキッズの僕にはワケワカランチンです。そのくせにクラスは[Function]って書いてあるし……。

追記:

「JavaScriptはすべてがオブジェクトだ。」というのは厳密には誤りで、「すべてがオブジェクトのように振る舞う」というのが正しい表現だそうです。(inoinojp さんありがとうございます)


JavaScriptはRubyのように“すべてがオブジェクト”の言語ではありません。primitiveなnumber/string/boolean/null/undefined/objectの6種類の型があり、ES2015のSymbol型を含めれば7種類の型があります。

"sample string" と "new String("sample string") は同値ではなく、前者はstring型、後者はobject型です。しかしstring型が "sample string".length のようにString Objectのプロパティにアクセスできるのは、内部で暗黙的なキャスト(これをオートボクシング:AutoBoxingと呼びます)が実行されているからです。

オートボクシングは、リテラルによって生成されたprimitiveな値に対応するコンストラクタから、ラッパーオブジェクトを生成します。プロパティへのアクセスが終了すると、このラッパーオブジェクトは破棄され、元のprimitiveな型へ変換されます。

したがって厳密に表現するのであれば“すべてがオブジェクトである”ではなく、“すべてがオブジェクトのように振る舞う”となるわけですね。


型についてのわかりやすい記事を見つけたので気になる方はどうぞ

JavaScriptの変数と型、値


それならオブジェクト型とは何か

ざっくりと説明すれば、「基本型以外です」



ES6から


ES6から.js

console.log(Animal)

//{ [Function: Animal] say: [Function] }
console.log(Animal.say)
//[Function]
console.log(hamaguchi);
//Animal {}
console.log(hamaguchi.say);
//[Function]

var ANIMALs = {dog:"わおん",cat:"にゃん",wotaku:"ぽきたwww魔剤ンゴwww!?",}
console.log(animals);
//{ dog: 'わおん', cat: 'にゃん', wotaku: 'ぽきたwww魔剤ンゴwww!?' }


なんということでしょう……!

いままで連想配列と関数がグチャグチャだった返り値が、Animal型というわかりやすい表示になっています。

また、生成したインスタンス(hamaguchi)は、ANIMALsとは別の物として扱われてます。

これなら変数がどう解釈されてるのかが一目瞭然です。


初心者にこれだけは伝えたい……

今回のclass構文は、JavaやC++の様に本質的なclassの仕組みが実装されたわけではありません。

糖衣構文という激アマな仕組みによって、prototypeカスが麗しいclassの形をしているだけなのです。

なので、本当はJSの基本的な考えである、prototypeチェーンを理解しなければ、JSを正しく使いこなせるとは言えないかもしれません。

でも、実際正直どうてもいい……


今日から使おうES6

ES6にはまだまだ便利な機能がたくさんありますが、とりあえず僕が一番感動した機能について紹介しました。

少しでも感動した方は下記の参考URLから、ES6の新機能をたくさん学びましょう。

今回のES6のような、モダンでシンプルなコーディングにもっと興味が湧いてくると思います。

そんで、さっさとJavaScriptから卒業しましょう!!


ちなみに対応状況

ここから見る事ができます。

http://kangax.github.io/compat-table/es6/

node.js なら、LTSであるv6を使うのがベストです。

が、v4以降であれば


strictモード

"use strict";


を使えば対応できます。

自分はよく使うモジュールが未だにv6に対応してくれないので、v5.6.0をstrictモードを用いて使ってます。

フロントエンドですが、遺跡ブラウザは見捨て…は出来ない方も多いと思うので、

babelのような、ES6記法のJSをES5以前のものに変換してくれるサービスもあるので、一度試してみるのは悪く無いかなと思います。


参考文献

class構文について

github Ecmascript

MDN ES6

MDN Classe

ES6 チートシート

もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)~