プロが教えるわが家の防犯対策術!

JavaScriptにはnullという値がありますが、いつ使うのでしょうか。
値が定義されていない変数やプロパティには、undefinedが入っていますし、
undefinedを代入することもできます。
C#でのnullの使い方と同じように、undefinedが使えちゃってます。

ではnullはいつ使うのでしょう?
undefinedではなくnullでなければダメなケースって何がありますか?

A 回答 (8件)

C# は知らないのでどう伝えるべきか迷いますが…、簡単に説明すると次のようになります。



・undefined … 未定義
・null … 値が存在するが falsy な値

JavaScript は型付けの緩い言語といわれますが、ある変数を定義したときその変数に格納される型を統一するのが一般的です。

---
var number = 1; // Number型の値を代入
number = -1; // 不要になったので falsy な値を入れる (ex: 0, -1, NaN等)
---

では、Object型はどうなるでしょうか。
ネイティブ実装されている関数は返り値の型に統一性があります。
Number型を返す関数なら必ずNumber型を返しますが、Object型を返す関数には二通りがあります。

---
var p = document.getElementsByTagName('p'); // p要素が全くなければ空のNodeListを返す

var string = 'Hello, World!';
console.log(string.match(/Hello/i)); // ["Hello"]
console.log(string.match(/Hoge/i)); // null (マッチしなければ null を返す)
---

このように null はObject型とセットで使われる場合があります。
空のオブジェクトはBoolean型に変換すれば true になりますが、null は false に変換されます。

---
if ({}) {
 console.log('{} は true に変換される');
}

if (null) {
 console.log('null は false に変換される');
}
---

undefined は未定義を表しますが、null は値を返した上で false であると明示している違いがあります。
あるプロパティに undefined を定義すれば、コードの書き方によっては「そのプロパティがない」と判断されてしまうかもしれません。

---
function hasProperty1 (object, property) { return typeof object.property !== 'undefined'; }
function hasProperty2 (object, property) { return property in object; }

var object = {hoge: 'Hello', foo: undefined};
console.log(hasProperty1(object, 'foo')); false
console.log(hasProperty1(object, 'piyo')); false
console.log(hasProperty2(object, 'foo')); true
console.log(hasProperty2(object, 'piyo')); false
---

hasProperty1 の書き方は間違いですが、undefined にはプロパティ未定義と同じ値を返す意味があることは覚えておく必要があります。
    • good
    • 0
この回答へのお礼

ありがとうございます。
機能上の違いというよりは、意味の違いの重視で可読性を上げるという観点ですね。

お礼日時:2012/01/23 08:57

恥ずかしながら、No.5 修正。


> function abort(message):Void
→ function abort(message):Never

> function display(message):Void { // この関数は処理を返さない
→ function display(message):Void { // この関数の戻り値は無効

---
なお、私は No.6 の taloo さんの使い方に概ね賛成です。JavaScript の「ユルさ」は、存在しないプロパティにアクセスしてもエラーにならず、undefined という「値」が返ってくることにあります。

しかしながら、存在しないプロパティにアクセスしたとき、なぜ undefined ではなく null を返すのではいけないのか? それは、分かりません。必ずしも駄目というわけでなく、歴史的な話のような気がします。

※詳しくは割愛しますが、JavaScript における null と undefined および型変換の扱いは最初期から混乱を極めています。JS 1.2 で整合性を図ろうとするも失敗し、JS 1.3 で厳密等価演算子 === とグローバル変数 undefined を導入することで、何とか今の状態まで持ち直しました。さらに MacIE との互換性まで含めると、本当に大変だったのです。

また、No.7 で指摘されているように、オブジェクト階層として null と undefined をどこに位置づけるかも問題になります。少なくとも、null をオブジェクトに含めるのは(No.5 に挙げたリンク先にも書かれているように)0 == 1 と見なすことになりますので、論理の根底を覆す大問題です。幸い、今でも null instanceof Object の方なら false になりますけどね。

さらにさらに、undefined は必ずしも「プロパティが存在しない」ことを意味しません。JavaScript では「プロパティが存在しない」と、「プロパティは存在するが値が undefined である」の 2 つの状態がありえますが、undefined だけではこれらを区別できません。だから、prop in obj のように屋上屋を架すような拡張がなされ、これがまた No.2 で触れられているようなラッパーとの衝突を生んだわけで。

次世代 ES では、この辺の意味論をすっぱり整理してほしい所ですけどねえ。No.5 で、実用化されていない型推論を引き合いに出したのはそのためです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
そういえばundefinedがグローバル変数であることも、
途中で仕様追加されたという経緯がありましたね・・・
確かにすっぱり整理してほしいです。
であればこんな質問も必要無かったんですが・・・

お礼日時:2012/01/23 09:07

To: #6 (taloo) さん



typeof null === 'object' は仕様バグとされています。
http://web.archive.org/web/20071110193102/http:/ …
http://d.hatena.ne.jp/think49/20120114/1326554107

次期ECMAScriptである ES.next では typeof null === 'null' に修正される予定です。
http://wiki.ecmascript.org/doku.php?id=harmony:t …
    • good
    • 0

文法、言語仕様による定義はちょっとわかりませんが、


私の考え、使い方は、
null:「明示的」な何も指定しないことの指定
undifined:「暗黙的」な何も指定しないことの指定

引数や代入には何も指定しないことを明示するわけですから、必然的に「暗黙」を使うことはなくなります。


function f(arg){
if(arg===undefined){
// デフォルト処理
}
}

f();
f(null);
f(undefined); //この使い方はしない


質問には関係ないと思いますが、nullはnullオブジェクトです。

alert( typeof(null) ); // 'object'
alert( typeof(undefined) ); // 'undefined'

JavaScriptでは、null、undefined、false、0、''(空文字列)がBooleanに型変換(キャスト)したときにfalseになり、
それ以外はすべてtrueになります。

a=null;
if( a ) {}
b=0;
if( b ) {}
    • good
    • 0
この回答へのお礼

ありがとうございます。
やはり機能上の違いではなく、意味分けして使うケースの方が多そうですね。

お礼日時:2012/01/23 09:05

「値がない」ことについて、今は亡き JavaScript 2.0(ECMAScript 4)には、Never 型、Void 型、Null 型の 3 つがありました。



Never は「値がない」本当の空集合です。処理を返しません。

function abort(message):Void {
 throw AbortException(message);
 // この関数は処理を返さない
}

Void は「値が無効」を示す undefined を一つだけ含む集合です。戻り値を無視して処理続行されます。

function display(message):Void {
 print(message);
 // この関数は処理を返さない
}

Null は「値がないかもしれない」を示す null を一つだけ含む集合です。値が null であるかがチェックされます。

function getHoge(obj):Object {
 if (...) return obj.hoge; else return null;
}

これらは、本当はコンパイラの型検証に使われるものです(でした)。実際に動かすまでもなく、コンパイル時点で「ありえない値」が来そうな部分はエラーないし警告を出す、ということです。

型検証のない現在の JS エンジンではあまり恩恵がないかもしれません。しかし、JS での動的な型検証の試みは多いので、将来的には何らかのツールが出るかもしれません。

---
E4X(ECMAScript for XML)では、次のように null と undefined を使い分けています。

・Namespace.prefix が空文字列ならデフォルト名前空間、undefined なら未宣言の接頭辞。
・QName.uri が空文字列なら名前空間なし、null なら任意の名前空間。

つまり、XML 文書で宣言されていない(後で XML 文書に書き出すときに特別処理が必要)な接頭辞に、とりあえず undefined を入れておきます。また、「任意の」を示すときに null を入れておきます。

そういう使い分けもある、という事例の一つとして。

※ DOM において null が多用されるのは IDL の制約によるもので、それ自体に意味はそんなにありません。

参考:
http://d.hatena.ne.jp/m-hiyama/20060314/1142304375
http://d.hatena.ne.jp/m-hiyama/20110704/1309737089
    • good
    • 0

>C#でのnullの使い方と同じように、undefinedが使えちゃってます。


使えるという事と、使うという事の違いですかね…。

undefinedは#1の方の言う通り未定義ですが、あえて意訳で未初期化と訳したいですね。
C言語やC++では(C#に非ず)、未初期化な変数は何が入っているか判らない変数です。
初期化せずに使うと、何が起こるか判らないパルプンテな状態です。

JavaScriptの仕様の制定者はそんなパルプンテ状態を嫌って、未定義で初期化する事を選んだんじゃないかという気がします(だから意訳としても未初期化と訳すのは完全に間違い)。

Cの流儀では未初期化な変数を使うのは恥ずかしい。
その流儀をJavaScriptに輸入すると、宣言時にvar hoge = null;と初期化してやればいいだけ。
※Cでは未宣言の変数は使えないので、宣言するというのもCの流儀の輸入
そもそも、undefinedを使う機会自体が存在しないってな感じなんですけどね。

ま、それはJavaScriptの流儀ではない、それはあくまでCの流儀だと言われてしまえばそれまでなんですが。

未定義を代入ってのは意味論的に見ると違うんじゃないかな、って気持ちがあるんですよね。
その気持ちを加味すると、意訳で未初期化と訳してしまいたくなります。
これも、個人の感覚を持ち込むなって言われてしまうとそれまでなんですが。

解答ではなく個人的意見の表明になってしまいましたが、そんな考え方もあるという事で。
    • good
    • 0
この回答へのお礼

確かにundefinedの意味を考えるとundefined代入は気持ち悪いですね。
実際に代入するケースはあまり無い気もしますが・・・

お礼日時:2012/01/23 09:00

#1,2 です。



某所で指摘を受けまして、「-1 は falsy ではない」ことに気がつきました。
Number型で falsy な値は「0, NaN」なので、#1 の冒頭は次のように訂正します。

---
var number = 1; // Number型の値を代入
number = 0; // 不要になったので falsy な値(0 or NaN)を入れる
---

失礼しました。
    • good
    • 0

#1 です。



null でなければ駄目なケースとしてはイベントハンドラの削除があります。
http://www.whatwg.org/specs/web-apps/current-wor …

---
function handleClick () { alert('onclick'); }
function sample () {
 element.onclick = handleClick; // element にonclickハンドラを定義する
 element.onclick = null; // elementのonclickハンドラを削除する
}
----

個人的には、null か undefined かはコードリーディングする上でわかりやすいかという側面が強いと思います。
その観点では「nullでなければ駄目なケース」より「undefined でなければ駄目なケース」の方が少ないですね。
少なくとも私は「不要になったら null で埋める」という使い方はあっても、undefined で埋めることはしたことがありません。
# jquery-1.7.1.js で見られる undefined の使い方も気持ち悪く感じます…。

話変わりますが、'onclick' in window === false な実装をしていた Firefox 4 の不具合は Firefox 9 では修正されているようです。
http://togetter.com/li/171744
この辺も undefined の扱いに違いが見られるところですね。
    • good
    • 0
この回答へのお礼

ありがとうございます。
そういえば確かに、イベントハンドラはnull代入のみでした。
それともう一点、document.getElementByIdも見つからないとnullを返しました。

お礼日時:2012/01/23 08:58

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!