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 と書くべきである。