nullとundefined
JavaScript(と、TypeScript)は、null
とundefined
という2つのボトム型(bottom type)があります。これらは異なる意味を持っています。
初期化されていない:
undefined
。現在利用できない:
null
。
どちらであるかをチェックする
現実としては、あなたは両方とも対応する必要があります。==
でチェックしましょう:
== null
を使ってundefined
と null
を両方ともチェックすることを推奨します。一般的に2つを区別する必要はありません。
1つだけ例外があります。次に説明するルートレベル(root level)のundefinedの値です。
ルートレベル(root level)のundefinedのチェック
== null
を使うべきだと言ったことを思い出してください。もちろん、覚えているでしょう(今、言ったばかりなので)。それは、ルートレベルのものには使用しないでください。 strictモード(strict mode)でfoo
を使うとき、foo
が定義されていないと、ReferenceError
exceptionが発生し、コールスタック全体がアンワインド(unwind)されます。
strictモードを使うべきです...現実としては、TSコンパイラはモジュール(modules)を使うときに、自動的に
"use strict";
を挿入します...後で解説を行うので、詳細は省略します:)
変数が_global_レベルで定義されているかどうかを確認するには、通常、typeof
を使用します:
undefined
の明示的な利用を制限する
undefined
の明示的な利用を制限するTypeScriptでは値と構造を分離してドキュメントのようにわかりやすくすることができます。下記のようなコードを想像してください:
これは、次のように型アノテーションを使用すべきです。
Nodeスタイルのコールバック
Nodeスタイルのコールバック関数(例: (err, somethingElse)=> {/* something */}
)は、エラーがなければ err
にnull
を設定して呼び出されます。開発者は一般的にtruthyチェックを行います:
独自のAPIを作成するときは、一貫性のためにnull
を使用することは、良くはありませんが、問題ありません。とはいえ、できればPromiseを返すようにするべきです。そうすれば、err
がnull
かどうかを気にかける必要はなくなります(.then
と.catch
を使います)。
値の有効性を表す意味でundefined
を使用しない
undefined
を使用しない下記は、ひどい関数の例です:
下記のようにする方が、はるかに良いでしょう:
JSONとシリアライズ
JSON標準では、null
のエンコードはサポートしていますが、undefined
のエンコードはサポートしていません。値がnull
である属性を持つオブジェクトをJSONにエンコードするとき、その属性はnull
値とともにJSONに含まれますが、値がundefined
である属性は完全に除外されます。
結果として、JSONベースのデータベースは、null
はサポートしますがundefined
はサポートしないことがあります。null
値を持つ属性はエンコードされるため、オブジェクトをエンコードしてリモートのデータストアに送る前に、ある属性値をnull
にすることで、その属性をクリアしたいという意図を明確に伝えることができます。
属性値をundefined
にすると、その属性はJSONにエンコードされないため、データのストレージと転送のコストを節約することができます。しかし、これによって、値をクリアすることと、値が存在しないことの文脈を曖昧にしてしまいます。
結論
TypeScriptチームは、null
を使いません: TypeScriptコーディングガイドライン。 そして、問題は起きていません。 Douglas Crockfordはnullは良くない考えであり、誰もがundefined
だけを使うべきだと考えています。
しかし、Nodeスタイルのコードでは、Error引数にnull
が標準で使われています。これは何かがおかしいです
という意味です。私は個人的に、ほとんどのプロジェクトにおいて、意見がバラバラのライブラリを使っていますが、== null
で除外するだけなので、2つの区別について気にすることはありません。
最終更新