
ワテがWEBプログラミングに挑戦したのが約10年前だ。
当記事はそんなワテがJavaScriptに関してAIさんとやった会話をAIさんにまとめてもらったものだ。
ワテの場合、2015年頃からJavaScriptやTypeScriptの勉強を始めた。
その頃、JavaScript初心者のワテが最初に戸惑ったものの一つが、undefined と null の違いである。
当時もいろいろ調べて、両者の違いについては理解したつもりだった。
つまり、
undefined は「値が設定されていない状態」
null は「何もないことを意図的に設定した状態」
ということである。
しかし、頭では理解できても、どこか釈然としないものが残っていた。
そして10年ほど経った現在、たまたま当時書いた以下の記事を読み返す機会があった。

この記事では、ワテ自身がundefinedとnullの違いについて悩み、いろいろ調べた内容を書いていた。
しかし、10年後の今、改めて読み返してみると、当時感じていた違和感の正体が少し分かった気がする。
では本題に入ろう。
undefinedとnullの違いが分からなかった10年前
当時のワテは、undefinedとnullの違いがよく分からなかったので、こんな関数を作っていた。
function isNullOrUndefined(value) {
if (typeof(value) === 'undefined' || value === null) {
return true;
}
return false;
}
要するに、変数の中身を確認して、
「これはundefinedなのか?」
「それともnullなのか?」
を毎回チェックしていたわけだ。
当時はJavaScriptとはそういうものなのだと思っていた。
また、ワテ自身のコーディングルールとして、
「変数を宣言したら必ず初期値を入れる」
という習慣を作った。
これは今でも良い習慣だと思う。
しかし、10年後に改めて考えてみると、別の疑問が出てきた。
問題はundefinedという状態ではなく、それを値として扱えることではないか
ここで考えてみたい。
変数を宣言したが、まだ値を入れていない状態。
これはプログラム上、確かに存在する。
let data;
この場合、
「dataという変数は存在するが、まだ値は決まっていない」
という状態である。
このような状態を持つこと自体は、別に問題ではないと思う。
しかし、JavaScriptでは、このundefinedという状態を通常の値と同じように扱うことができる。
例えば、
data = undefined;
のように代入できる。
また、
if (data === undefined)
のように条件判断もできる。
ここにワテは違和感を覚える。
未定義状態は値ではなく、言語側が管理すべきではないか
ワテが思う、より自然な設計はこうだ。
変数を未初期化状態で作ること自体は許してもよい。
しかし、その変数を実際に利用しようとした瞬間に、
「この変数にはまだ値がありません」
というエラーを出せばよいのではないか。
つまり、undefinedという状態は内部的には存在してもよい。
しかし、それをプログラマーが普通の値として操作できるようにする必要はなかったのではないかと思う。
例えば、
if (data === undefined)
のような判定をプログラマーが書く必要があること自体が、少し不自然ではないだろうか。
undefinedを値にしたことで増えた管理項目
プログラムを書く側から見ると、undefinedが存在することで、常に考慮すべき状態が一つ増える。
つまり、
- 通常の値が入っている
- nullである
- undefinedである
という複数の状態を意識しなければならない。
もちろん、状態を細かく区別したい場合もあるだろう。
しかし、本来なら言語処理系が管理すべき「未完成な状態」を、プログラマーが毎回チェックする必要があるという点は、設計として少し疑問が残る。
TypeScriptが広まった理由も、この問題と関係しているのではないか
現在では、JavaScriptよりTypeScriptを使う開発者も多い。
TypeScriptでは型チェックによって、実行前に問題を発見できる。
これは、ある意味ではJavaScriptの弱点を補う方向の進化と言える。
つまり、
「実際に動かしてから問題を発見する」
のではなく、
「動かす前に問題を発見する」
という方向である。
最近のプログラミング言語ではどうなっているのか
ちなみに、このundefinedのような問題は、最近のプログラミング言語ではどのように扱われているのだろうか。
結論から言うと、JavaScriptのように「未定義状態」を通常の値と同じように扱う設計は、現在の主流ではなくなってきているように思う。
例えばRustでは、値が存在しない可能性がある場合にはOption型を使う。
SwiftではOptional型、Kotlinではnullable型という仕組みによって、「値が存在しない」という状態を型として明示的に管理する。
つまり最近の言語では、
「値がない状態を表現すること」
そのものを否定しているわけではない。
問題なのは、それを通常の値と同じレベルで自由に扱えてしまうことである。
未定義状態は言語側が管理し、プログラマーが必要以上に意識しなくても安全に扱えるようにする。
この方向が、現在のプログラミング言語設計の大きな流れなのではないかと思う。
そう考えると、10年前にJavaScriptのundefinedに感じた違和感は、単なる初心者の戸惑いではなく、後の時代の言語設計が向かった方向と一致していたのかもしれない。
まとめ

十年一昔と言うけれど、ワテの場合は五年前の事ですら遠い過去に感じる。
10年前、JavaScriptを学び始めた時、ワテはundefinedとnullの違いに悩んだ。
当時は単純に、
「JavaScriptは分かりにくい仕様があるな」
と思っていた。
しかし、10年後に改めて考えてみると、問題の本質はundefinedという概念そのものではなかったように思う。
未定義状態を持つこと自体は必要な場合もある。
しかし、それをnullや数値などと同じ「値」として扱えるようにしたことで、プログラマー側に余計な管理負担が発生したのではないか。
状態は状態として管理する。
値とは分ける。
そして、その状態を利用しようとした時には、言語側が警告する。
そのような設計の方が、プログラマーにとっては分かりやすく、安全な言語になるのではないかと思う。
10年前に感じた小さな違和感。
それは10年後の今になって、単なる初心者の戸惑いではなく、プログラミング言語の設計思想に関する疑問だったのだと気付いた。
(つづく)

コメント