JS void 禁止令
その昔、JavaScript で undefined を得るためには window.undefined
こと undefined
を使うのではなく、void(0)
を使おうという啓蒙があった。
void(0) の有用性
なぜ素直に undefined
と書かずに void(0)
と書いたほうがいいのか。それは、当時、window.undefined
が書き換え可能な変数だったからである。仮に undefined = 0
とし 0 の代入を試みた場合、成功する時代だった。なので、undefined
という変数の中身が必ずしも undefined であるという保証がなかった。ゆえに、いつでも確実に undefined を取得できる void(0)
という表記が、有識者に好まれていた。
現代の window.undefined
時は経ち、現在 2013 年。状況は変わっている。最近のブラウザでは、window.undefined
の書き換えができなくなっている。よって、undefined
変数には、いつでも必ず undefined が入っている。なので、わざわざ void(0)
という、非直感的な表記を徹底しないで、積極的に window.undefined
を採用することを躊躇する必要はない。いや、むしろ、void 演算子は一切使用せず、undefined
のみを使っていくべきである。その表記のほうが分かりやすいからだ。
グローバルスコープにおいては、以下のコードのように、window.undefined
を参照することによって、いつでも undefined が得られる。
<script> undefined; </script>
ローカル変数としての undefined
ただし、関数の内側ことローカルスコープでは、undefined
変数がいつでも undefined を保持しているとは限らない。
ローカル変数として宣言した undefined
は、自由に代入可能なのである。
以下のコードは、その具体的例である。
(function () { var undefined = 0; return undefined; })();
このコードでは、関数内において、undefined
変数を作成し、0 を代入している。最後に return undefined
しているが、これは return 0
と等しい。
ローカルスコープにおいて、確実に undefined を得るには void(0)
あるいは (function(){})()
などを使用するしかない。
グローバルスコープでは undefined
を使い、ローカルスコープでは void(0)
を使う、というふうに、使い分けるのも最悪ではないが、一貫性がないために、混乱の元になる。そして、めんどうであり、美しくない。
では、やはり undefined
変数ではなく、いつでも void(0)
で undefined を得るのが正しいのだろうか。
いいえ。
Array 関数を参照できなくする
たとえば、window.Array = 0
として、Array
変数を上書きしたとする。すると、Array
変数は、配列のコンストラクタであり Array.isArray
などの便利機能を有する Array 関数ではなくなり、0 になってしまうのだ。つまり、window.Array
がいつでも Array 関数である保証はない。くわえて、いつでも Array 関数を得る方法は存在しない。[].constructor
には、いつでも Array 関数が入っていそうだが、そうではない。
Array.prototype.constructor = 0; [].constructor; /* is not Array */
上記のように、Array.prototype.constructor
を上書きすることで、[].constructor
を参照しても Array 関数を取得することをできなくすることができる。
これが JavaScript の柔軟さである。
Array
変数に Array 関数が入っているとは限らないので、Array
変数は使うべきではないとすることはできない。他に Array 関数を取得する方法がないからだ。ならば、確実性は諦めて、Array
変数を使っていくしかない。
undefined 変数作成禁止令
同様に、ローカル変数としての undefined
には確実性を求めず、使っていくしかない。いや、そもそも、ローカル変数として undefined
を作成するべきではない。undefined
という名前の変数は、分かりやすさのため、いつでも undefined を参照しているべきである。だから、window.undefined
だけが唯一の undefined
変数であるべきであり、これ以外に undefined
変数を作成することを自主的に禁止していくべきである。
さらに、以下のようなコードを書くべきではない。
(function (undefined) { /*...*/ })();
このコードでは、仮引数として undefined
変数を作成し、そこに、undefined を渡しているのだが、あまり意味がない。window.undefined
以外に、新たに undefined
という名前の変数を作成するな、という話はさておく。仮に、上記のような、確実そうに思える undefined 取得方法は、実は確実ではない。
(function (undefined) { undefined = 0; })();
関数内では、仮引数である変数に、代入を行うことができるからだ。
void の終焉
そもそも void 演算子とは、javascript:
スキームの URL にアクセスした際、ブラウザの画面遷移を起こさせないために存在していた。HTML の a 要素の href 属性の値として javascript:void(0)
を入れておく慣習があった。だが、今や、もう、そのようにしなくとも、イベントハンドラで event.preventDefault()
を行うことで、ステータスバーには気の利いた文字列を表示しつつ、画面遷移も抑えるという方法が普及している。
void の役目は終わった。
まとめ
undefined を確実に得るためには、最近のブラウザなら書き換え不可能な window.undefined
を使えばいい。undefined 以外にも Array 関数や String 関数など、確実に得られるべきものたちはたくさんある。そのほとんどについて、確実な取得方法は存在しない。コードは、一箇所でも壊れると、うまく動かなくなることがある。undefined だけを確実に得る意味はない。だから、void(0)
というような分かりにくい表記をやめて、undefined
と書くべきである。