#だから僕はVanilla JSを辞めた
Vanilla JSとは、普通の何のフレームワークも使わない純粋なJavaScriptのことです。
Pure JSと呼んだりもしますが、あえてこの表記としています。
私が、フレームワークに手を出して、Vanilla JSを辞めた理由を、私の場合の例として述べます。
私の場合がTypeScirptとVue.jsの導入だったのでその話をしますが、これらの推奨が目的ではなく、新たなものへ挑戦する勇気を持ちなさいという記事です。
##TL;DR
- 純粋なJavaScriptでなんでもできるからと、なんでもしていた私がフレームワークを導入するまで
- フレームワークや、その他新しいことの食わず嫌いはなるべくやめたい
JavaScriptだけで記述する
WEB開発はコンパイラ不要、環境も選ばない、JavaScriptはなんだか緩いと、手を出しやすい分野だと思います。
私はなんでも純粋な状態で書くことに、何と無くこだわりを持っていました。
JavaScriptだけで書いて、jQueryなどには見向きもしない、そんな日々が続いていました。
その理由としては、新たなものを覚えるほどまだJavaScriptに精通していない、学習コストが高そう、無くてもかける、無駄な通信や変数汚染を避けたい、などでした。
TypeScriptとの出会い
しかしそんなある日、何気なく書いた次の一文が動かないことに頭を悩ませることになります。
document.getElementsByTagName("a").forEach((e) => {
e.onclick = () => location.href = e.href
e.removeAttribute("href")
})
内容は、ページ中のa
タグのリンクを消去し、代わりにonclick
でページ遷移を行うものです。
これは、PWAでa
タグによるリンクを行うと、PWAを抜けてブラウザが起動してしまうというものを回避するために書いたものでしたが、うまく動作しません。
この理由は、document.getElementsByTagName
の戻り値はHTMLCollection
であってArray
でないことです。
今まで考えてもいませんでしたが、JavaScriptにも型が存在したのでした。
上記ではHTMLCollection
というのはObject
型であり、そこにforEach
メソッドが定義されていないため、動作しないのです。
どうにもJavaScriptばかり書いてると、型の考えをしなくなってきます。今でこそlet/const
による記法が標準となってまいりましたが、古い本などではvar
を用いるものも見ます。なんだって再代入できちゃうものだから、動的型付けなんて型がないみたいなものだろうと考えてしまいます。
そして思い出したキーワード、それがTypeScriptです。
型を意識しないでめちゃめちゃなことできるからJSは便利なのに、なんでそこに型付けるのか、非常に疑問でしたが、これ使ってたらこんなエラーに数時間溶かすことはなくなるのではないかと、思ったわけです。
簡単な例
次のようなコードを書いたことがあるでしょうか
console.log(`${num} is ${(num % 2) ? "odd" : "even"}`)
上記は、数字の入った変数num
によって、それが偶数か奇数かをコンソールに表示するという動作をします。
なぜでしょう。それは0
がfalthy
で、それ以外の数字はtruthy
だからですね。
JavaScriptでは暗黙の型変換が結構活躍します。条件式の中では勝手Boolean
に変換される上記の例もそうですが、ほかにも
const num = document.getElementById("age").value - 0
などとすれば、入力された数値をString
型ではなくNumber
型として利用できます。
これは、文字列に算術演算子を適用するとき、文字列を数値へ暗黙的に変換を行うためで、実際には数値へ変換できないような文字列だとしたらNaN
が代入されることになります。
一見便利な暗黙の型変換ですが、変数に入っている方がわからなければ、先ほど挙げたHTMLCollection
のような、無いメソッドを呼び出してしまうようなミスをしてしまうことが多くなってきます。
TypeScriptでは、変数に代入できる型や、メソッドの戻り値の型などはあらかじめ決めておかなければなりません。このため、上記のコードはコンパイルが通りません。算術演算子の左オペランドには文字列は使えないからです。(文字列の結合の演算子としての+
は使用できますが、これは算術演算子ではありません)
これは逆に、変数の型は常にわかっているということです。
なんらかのコードエディタを用いている場合、変数の型がわかっているために、メソッドなども書いている途中でその有無や戻り値の型まで把握できます。
最近はNull安全などといったことも目にしますし、ECMAScript2020ではOptional Chaning演算子?.
や、Null合体演算子??
も追加されます。null
の扱いは面倒ですからね。
一方でTypeScriptではそもそも、その変数がundefined
やnull
となり得るかどうか知ることができます。
なり得る場合は、先述のような演算子や、条件分岐などを必要としますが、それを教えてくれるというわけです。便利ですね。
簡単な例2
次のコードの動作はどうなるでしょう。
const num = 5
window.localStorage.setItem("isEven", !(num % 2))
const isEven = window.localStorage.getItem("isEven")
console.log(`${isEven ? "even" : "odd"}`)
当然5
は奇数ですからsetItem
されるのは!(5 % 2) = !(1) = false
です。
それがisEven
にローカルストレージ経由で代入され、三項演算子で"odd"
と評価されるはず、と思いますよね。
残念ながら、num
が5
であろうとなんであろうと、コンソールの表示は必ず"even"
になります。
ローカルストレージには文字列しか保存できないんですね。
このため、setItem
の時点でfalse
は"false"
に変換され、truthy
となります。
今回の場合、setItem
されるのは"true" | "false"
と表せます。これはどちらもtruthy
ですから、常に"even"
が表示されます。
型変換されるとわかっていても、必ずJSON.stringify
してからセットし、読みだした後にJSON.parse
するようにしないといけませんね。
一方、TypeScriptでは、Boolean
型はString
型じゃないよって教えてくれます。また、読み出し後もそれがString
型であることを教えてくれるので、このようなミスは防げるかと思います。
シチュエーションとしては、チェックボックスやスイッチの状態を保存したいときなんかあると思います。
自分もやらかしてしまいそうだと思いませんか?
なぜかundefined
って画面に出ちゃうことがある人は検討してみると良いでしょう。そもそも画面に表示するところにundefined
となり得る変数を置かなければ良いんですから。
型変換を自前で行う必要がある場合や、変数の型を明記する必要がある場合など、コードの記述量は増えてしまうことはあるかもしれませんが、その分バグが減ります。
今まで環境構築や学習コストなどを恐れて導入しなかった昔の自分を諭したいです。
Vue.jsとの出会い
そしてある日、Vue.jsというものを見かけます。
どうやらアプリ開発に便利なフレームワークだそうです。
フレームワークはとはなんや、と思いましたが、流行ってたので乗ることにしました。(コロナも流行ってますが乗らないでください)
とりあえず適当にアプリを開発して、Vuetifyというマテリアルデザインのアプリ開発が簡単にできるものも見つけ、使用しているうちにこう感じましたわけです。
「なるほど。今までは車輪の再発明をしていたわけか。」
あるいはjQueryなんかも使っていればもっと早くアプリの開発ができたのではないかとも、今になっては思います。もう今となっては使いませんが。
先人が自分より高度な知識で作ったものなんですから、そりゃ私がそれに勝るアプリを作れないでしょう。
それはもう、Array
にはArray.prototype.reverse
があるのに、自前でfor
文で逆に詰めなおすようなことをしているようなものだったわけです。時間の無駄だし、なんなら性能も劣る場合があります(ソートなんかそうですね)。
だから僕は
今までの私は間違っていました。
使用できるものは使った方が良いです。なんかnull
になったり、予期しない文字列きたり、対応するのめんどくさいですね。デザインなんかコーディングと同時にするには難しいですし、CSSはいつも思ったのと違う動作するんですもん。
そして私は今になって、昔の開発環境を、あるジョーク記事からとってこう呼んでいます。
Vanilla JSと。
それは、純粋なJavaScriptを用いるというフレームワークです。
初学者なんかは構いませんが、ある程度の規模になってくると注意深い開発が必要になり、他人と開発するときなんかにもそのメソッドが何を返す可能性があるのかを明確にしたいときが出てきたりすると思います。
私の場合、TypeScript+Vue.js+Vuetifyというのを採用して、開発の効率と品質が上がり、食わず嫌いで導入を渋っていたことを後悔しました。
だから僕はVanilla JSを辞めた。