JavaScriptのclass構文を使って「ASUS」を読む
ほとんどネタ記事。
Twitterで「ASUS」の読み方の話題がトレンドに入っていたので、勢いでASUSの読み方を表示するJavaScriptを作った。
※ 下記の通り、読み方論争は公式には決着済の話。
「ASUS」読み方論争に決着 「エイスース」に統一 - ITmedia NEWS
ASUSを読むボタン
まずは見たほうが早いので、作った結果を。ランダムにASUSの読みを表示してくれる。
ECMAScript 2015依存なので動かないブラウザもあると思う。
ボタン実装のコード
こんなかんじでJavaScriptを書いている。
/** * AsusTokenクラス * ASUSの文字(列)の読みと次に続くAsusTokenを定義 */ class AsusToken { constructor() { // 配列で読み方の候補を定義する // 読み方は配列要素からランダムに選択される。 this.reads = ['ダミー']; // 次のTokenを示す。 // null の場合は終端のTokenであることを示す this.nextToken = null; } /* * 現在のトークンの読み方を取得(候補の中からランダムで取得) */ get read() { return this.reads[Math.floor(Math.random() * this.reads.length)]; } } class SToken extends AsusToken { constructor() { super(); this.reads = ['ス']; this.nextToken = null; } } class SUToken extends AsusToken { constructor() { super(); this.reads = ['サー', 'スー', 'サ']; this.nextToken = new SToken(); } } class AToken extends AsusToken { constructor() { super(); this.reads = ['エー', 'エイ', 'ア']; this.nextToken = new SUToken(); } } /** * 文字列ASUSの読み方を取得する */ function getReadOfASUS() { var readAsus = ''; // "A"のTokenから開始し、次のTokenが無くなるまで読みを結合 var token = new AToken(); while(token != null) { readAsus += token.read; token = token.nextToken; } return readAsus; } /** * 文字列ASUSの読み方を画面に表示する */ function showReadOfASUS() { document.getElementById('ASUSText').textContent = getReadOfASUS(); }
あとはHTMLにscript, 発火用のボタン, id="ASUSText"のテキスト要素を仕込む。
使われている要素:class
ECMAScript 2015で追加された構文。
Javaなどのクラス定義に慣れていると、functionやprototypeで定義する構文よりもこの書き方のほうがすっと入ってきそう。
実装や調査時こちらのページを参考にさせていただきました。
JavaScriptにもクラスがやってきた!JavaScriptの新しいclass構文をマスターしよう | HTML5Experts.jp
ES2015新機能: JavaScriptのclassとmethod - Qiita
対応状況
このあたりから確認できる。ECMAScript 6 compatibility table
執筆時点の対応状況はこんなところか。(各ブラウザの最新を利用している前提)
使えそう | Edge, Chrome, FireFox, Opera, Safari, iOSのSafari |
---|---|
使えなさそう | IE, Androidブラウザ*1 |
Androidがダメってのが痛い。
広く一般への利用を求める場合、現時点では利用を避けたほうが良いのかも。
classに定義できるもの
コンストラクタ、getter, setter, メソッド定義など。
メンバ変数(プロパティ)を定義する構文はなさそう。
それっぽいものを定義する場合、コンストラクタでの初期化で定義するか、getter/setterを使って定義することになる。
個人的にはメンバの定義箇所が分散してほしくないので、コンストラクタで定義するほうが好み。
コンストラクタ
constructor
の名称で定義するメソッドがコンストラクタになる。
super()
と書けば、Javaの如く親クラスのコンストラクタを呼べる。
複数定義するとSyntax Error
となる。
getter/setter
Javaのgetter/setterの先入観でちょっと戸惑った所。
使い方が異なる。とりあえずJavaとだけ比較するとざっくりの違いは下記の通り。
言語 | 使う時の書き方 |
---|---|
Java | 明確にメソッドを通じてデータを操作する書き方となる。 |
JavaScript | 利用者から見ると、データを直接操作するような書き方となる。実体は定義したメソッドを通じてのデータアクセスとなる。 |
構文で比較するとこんな感じ。
言語 | getterを使う時の構文 | setterを使う時の構文 |
---|---|---|
Java | hoge = obj.getHoge(); |
obj.setHoge("hoge"); |
JavaScript | obj.hoge = 'hoge'; |
hoge = obj.hoge; |
JavaScriptは元々getXxx()
やsetXxx()
といったメソッドは作らない。
メンバにアクセスする場合は直接アクセスする。
(スコープでメンバ隠蔽するような構文もないし)
でもって、getter/setterも同じような形でアクセスできるようになっている。
サンプル
class Sample { constructor() { /* No def */ } /* * hogeプロパティがなくても、 * hoge = sample.hoge; といった書き方をするとこのメソッドが呼ばれる. */ get hoge() { return this._hoge; } /* * hogeプロパティがなくても、 * sample.hoge = 'fugafuga'; といった書き方をするとメソッドが呼ばれる. */ set hoge(value) { this._hoge = value; } }
メソッド定義
function
とか書かなくてもメソッドが定義できる。
あまり説明することは無いので、サンプルコードだけ。
サンプル
class Sample { constructor() { /* No def */ } /* * これでSampleクラスにexecメソッドが追加される。 */ exec(arg1, arg2) { /* 処理定義 */ } }
setter/getter/メソッド定義の補足
setter/getter/メソッド定義はclass
と一緒に使うことが多そうだが、これらは短縮記述用の構文として別定義されているもの。
class構文を使わず、別の箇所で利用することもあるようだ。
参考:
Method definitions - JavaScript | MDN
setter - JavaScript | MDN
getter - JavaScript | MDN
まとめ
- class構文でJavaScriptでクラス定義ができる。
- 古めのブラウザを動作対象にしたい場合は微妙かも。*2
- コードの見通し的に使えるなら使ったほうが幸せになれそう。
- ASUSの正しい読みは「エイスース」。