JavaScriptの変な書き方が嫌い

JavaScriptって、最初はオブジェクト指向の概念がなかったんですよ。
ES2015っていうバージョンでできるようになったのすが、2015年ってめちゃくちゃ最近じゃないですか。
あとからあとから機能が追加されて、しかも他の言語とちょっと違う書き方が多くてすごく気持ちが悪い言語。
しかも昔はブラウザによって動いたり動かなかったりということが多くて、正直言って大嫌いな言語でした。

少し前まで、要件でIEで動くように見たいなものもあったので、あんまり新しい仕様の記述はさけたりしていましたが。
ですので、フロントエンドで何かしたいときは、基本的にjQueryを使っていたんですが、そろそろオワコンっていう声も聞こえてくるし、VueとかReactとかSPA(Single Page Application)ってのもそろそろメジャーになってきたので、さすがにもうIEも絶滅しただろうし、まじめに最新のJavascript技術をやっていこうかなという今日この頃です。

まずは、JavaScriptの気色悪い関数宣言方法についてまとめていこうかと思います。

スポンサーリンク

関数宣言(function文)

こんな感じです。

//function(関数)の定義
function test(){
  console.log("hoge");
}
//呼び出し方法
test();

どの言語でも共通する一般的な関数宣言の方法だと思います。
私は基本この方法で書いています。
因みに、関数定義の前に関数呼び出しが来ても大丈夫です。C言語なんかはダメなので、先に定義するか定義ファイルを読み込むかする必要がありますが、JavaScriptの場合は関数宣言だけ先に読み込んで登録してくれるようです。
問題は次です。

関数式

//function(関数)の定義
let hoge = function (){
  console.log("hoge");
}
//呼び出し方法
hoge();

関数を変数に代入している感じですかね?オブジェクト指向とはちょっと違う書き方で気味が悪いです。
JavaScript以外でこういう表記法があるのかわかりませんが、少なくとも主要な言語でこういったことができるのはJavaScriptだけだと思います。
強いて近い感じの機能をあげるとすれば、C言語の関数ポインタでしょうか?
因みに、関数名がない関数定義を無名関数(もしくは匿名関数)と呼びます。
無名関数はほかの言語にもあったりします。(PHPにもありますね)
また、関数名はついていても構いません。構いませんがどうやって使うんだろうか?

関数名を考えなくても関数を定義できるというのが利点といわれています。まぁ、この場合は代わりに変数名が必要なので、結局同じなのではというような気がしますが…。
とはいえ、SPAのフレームワークだと大体この書き方をしているので、この書き方にも慣れておかないといけないでしょう。
まぁ、本当は別の理由があるのです(後述)

無名関数

無名関数は他の言語でもあるのですが、なぜかJavaScriptはこの書き方を多用する傾向があります。
たとえば。

fuga = hoge(function(){
  console.log("hoge");
});
fuga();

関数の引数に、別の関数の戻り値を入れたいっていう場面は結構あるんですが、これを無名関数でやることが多いんですよね。
数行の小さい関数ならまぁいいんですが、1画面以上のデカい関数とか、関数内で別の関数に対してこの処理が入ると、さらに長くなっちゃう傾向があります。
そうなると、書いてるときはいいのかもしれませんが、いざコード解析しようというときに非常に見通しがわるいんですよ。
一般的に関数を長くしてはいけません、別の関数に分けましょう、と言われているのですが、JavaScriptはなぜかガン無視してますよね?

だから嫌いなんだよ

アロー関数

無名関数の記述方法でこういうのが追加されました。

//今までのやり方
function(a, b) {
return a + b
}
//アロー関数
(a, b) => {
return a + b
}

functionって書いてたのを=>にできますよっていうただそれだけの話です。
ちなみにPHPでも7.4でこの記法が追加されました。
=>はアロー演算子・・・でいいのかな?
ふつう、アロー演算子ってC言語の構造体とかオブジェクト指向でインスタンスが持ってるプロパティーを指定するのに使ったりしてますね。

即時関数

無名関数関連で即時関数も語らないとだめですね。
こういうやつです。

(function () {
    //処理
}());

jQueryとかで何かするときにとりあえずこれの中に処理を書きますね。
普通の無名関数との違いは、即時関数はその名の通りすぐ実行されます。
なんでこんなのを使うかというと、変数のスコープ汚染を防ぐためです。
スコープというのは、定義した変数がどこからどこまで使えるかということです。
一般的な言語は、アプリケーション全体、定義したファイル内、関数内、ブロック内 の4パターンがデフォルトの範囲で、言語によっては名前空間という定義ができて、自由にスコープを設定できます。

で、JavaScriptなんですが、基本的にブロックスコープの概念がありません。つまり、プロジェクト(HTML内とかリンクしたJSファイル内で)全体で、別の用途で使っている変数の名前がかぶっちゃうと、バグの原因になります。
よって、即時関数で書くと、関数になってスコープが付くので安全になるというのが本当の理由です。

ですが、ES2015以降は”let”で宣言して使えばブロックでのスコープが付くようになりました。
ですので、本当はこんなことしなくてもいいはずなのですが、JavaScriptのネイティブスピーカーたちは即時関数に慣れすぎてしまって、結局使っているんですよね。

型なし言語

変数宣言の話も出てきたので、型についても触れないといけません。
型というのは、変数にどんなものを入れるかの定義のことで、数値なら数値型、文字列なら文字列型で宣言しします。比較的古い言語は静的型付け言語といって、宣言した型に合うデータしか代入できません。
一方、JavaScriptは変数宣言時にデータ型を指定する必要がありません。スクリプト実行時に、必要に応じてデータ型が自動的に変換されます。こういった言語を動的型付け言語といいます。
動的型付け言語は、一見便利なように見えますが、バグの温床になります。数字と文字列で計算とかもできちゃうわけですからね。ちなみに、Pythonも動的型付け言語です。
PHPは一応、静的型付け言語ですが、厳格ではなく、たとえば一致しない型が引数と渡されたても、一致させることができる場合暗黙の型変換がなされます。これも一見便利ですが怖いですよね。

一応、JavaScriptでもTypeScriptを用いて型付にする方法があります。
TypeScriptはJavaScriptのスーパーセットですので、JavaScriptと同じ方法で記述できます。ただ、作ったのがマイクロソフトなんですよね。あの会社が作ったものっていきなり梯子を外してなかったことにすることがあるので、あんまり勉強したくないんです。将来的にTypeScriptが持つ機能がJavaScript本体にも導入される可能性も無きにしも非ずなので・・。まぁオープンソースなのでなくなるってことはないとは思いますが、選択肢の一つとしてもいいかもしれません。

プログラミング初学者の方へ

Webアプリケーションエンジニアを目指そうとしている方は、フロントエンドとバックエンドどっちがいいかという議論がありますが、最終的にはどっちもやったほうがいいでしょう。
両者は密接にかかわってます。どっちに軸足を置くかは自由ですが、両方できないと話にならない場合が多いかなと思います。
ただ、最初に学ぶのはバックエンドのほうがおすすめです。
理由は、フロント側の言語は実質JavaScriptしかないのですが上記のように同じ処理に対して記述方法が複数あり、直感的にわかりにくく、初心者には混乱する原因になると思います。
また、私の感覚では、これらの記述方法のせいで、コードが非常に汚い、と感じます。初心者の次のステップとして、コードを読むというのが非常に大切ですが、汚いコードは読むのが大変です。
こういった汚いコードを読むには、RubyなりPHPなりである程度プログラミングの感覚を養ってからのほうがいいと思います。

また、起業家を目指していて、自分でサービスを作りたいみたいな方は、とりあえずフロントはjQueryを使う方向を検討したほうがいいかと思います。JSで動くアクションゲームを作るとか突飛なことでない限り、計算したりHTMLを操作する程度なら、サンプルをコピペしてパラメータを変える程度ですぐできるようになります。複雑な処理もライブラリを使えば事足ります。

何かしら本を買って基礎的なことを学んでおけば、あとはネット上の情報で大体のことは困らないと思いますのでお勧めです。

コメント