LoginSignup
4
0

More than 3 years have passed since last update.

だから僕はVanilla JSを辞めた

Last updated at Posted at 2020-07-03

だから僕は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によって、それが偶数か奇数かをコンソールに表示するという動作をします。
なぜでしょう。それは0falthyで、それ以外の数字はtruthyだからですね。

JavaScriptでは暗黙の型変換が結構活躍します。条件式の中では勝手Booleanに変換される上記の例もそうですが、ほかにも

const num = document.getElementById("age").value - 0

などとすれば、入力された数値をString型ではなくNumber型として利用できます。
これは、文字列に算術演算子を適用するとき、文字列を数値へ暗黙的に変換を行うためで、実際には数値へ変換できないような文字列だとしたらNaNが代入されることになります。

一見便利な暗黙の型変換ですが、変数に入っている方がわからなければ、先ほど挙げたHTMLCollectionのような、無いメソッドを呼び出してしまうようなミスをしてしまうことが多くなってきます。

TypeScriptでは、変数に代入できる型や、メソッドの戻り値の型などはあらかじめ決めておかなければなりません。このため、上記のコードはコンパイルが通りません。算術演算子の左オペランドには文字列は使えないからです。(文字列の結合の演算子としての+は使用できますが、これは算術演算子ではありません)

これは逆に、変数の型は常にわかっているということです。
なんらかのコードエディタを用いている場合、変数の型がわかっているために、メソッドなども書いている途中でその有無や戻り値の型まで把握できます。

最近はNull安全などといったことも目にしますし、ECMAScript2020ではOptional Chaning演算子?.や、Null合体演算子??も追加されます。nullの扱いは面倒ですからね。
一方でTypeScriptではそもそも、その変数がundefinednullとなり得るかどうか知ることができます。
なり得る場合は、先述のような演算子や、条件分岐などを必要としますが、それを教えてくれるというわけです。便利ですね。

簡単な例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"と評価されるはず、と思いますよね。

残念ながら、num5であろうとなんであろうと、コンソールの表示は必ず"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を辞めた。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0