JavaScriptに「null」値があるのはなぜですか?


115

JavaScriptには、基本的に「私は存在しない」と言う2つの値があります- undefinednull

プログラマが何も割り当てていないundefinedプロパティはになりますが、プロパティがになるためにはnullnull明示的に割り当てる必要があります。

は、プリミティブな値とオブジェクトであるnullため、必要があると思っていました。それは、もし降伏しても、そうではありません:実際には、両方ともプリミティブ値です-つまり、どちらでもありませんundefinednulltypeof null'object'undefinednull両方が空のオブジェクト(1はコンストラクタでPROCLAIM失敗にエラーをスローすることがある)に変換されるように、コンストラクタ関数から返すことができます。

また、どちらもfalseブールコンテキストで評価されます。私が考えることができる唯一の本当の違いは、一方がに評価されNaN、もう一方が0、数値コンテキストです。

それでは、なぜ両方がundefinedありnull、これがnull、プロパティが設定されているかどうかを調べようとするときに誤ってチェックしているプログラマを混乱させるだけなのでしょうか。

私が知りたいのは、誰かがそれを使用しnullて表現することができなかった使用する必要がある合理的な例があるかどうかですundefined代わりに。

したがって、一般的なコンセンサスは、undefined「そのような財産は存在しない」ことを意味するようです。null手段は「プロパティが存在していますが、何も値を保持していません」。

JavaScriptの実装が実際にこの動作を強制する場合は、私はそれに耐えることができますundefinedが、完全に有効なプリミティブ値なので、このコントラクトを破るために既存のプロパティに簡単に割り当てることができます。したがって、プロパティが存在するかどうかを確認する場合は、とにかくin演算子を使用する必要がありhasOwnProperty()ます。もう一度言いますと、undefinednullですか?

使用undefinedしなくなったが、使用したくないプロパティの値を設定解除したい場合は、実際に使用します。deleteます。null代わりに使用する必要がありますか?


3
最後の質問に答えるには:いいえ、プロパティをに設定するべきではありませんundefined
Shog9 2009年

4
「undefined」は、プリミティブ値「undefined」を持つグローバルスコープ内の変数です。変数に別の値を定義することは可能です:{undefined = "Hello"; アラート(不定);}をテストするAより信頼性の高い方法未定義:{(typeof演算MYVAR === "未定義")、警告( "未定義")}もし
一部

1
undefined / nullについてはecma-international.org/publications/files/ECMA-ST/Ecma-262.pdfのセクション4.3.9-12 を、グローバルスコープの変数 "undefined"については15.1.1.3を参照してください。
いくつかの

1
オブジェクトを削除するか、それが理にかなっている場合はnullに設定する必要がありますが、未定義にしないでください。
いくつかの

4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.いいえ、それだけをundefined言います。
2014

回答:


78

問題は、「JSにnull値があるのはなぜですか」ではありません。ほとんどの言語には、ある種のnull値があり、一般に非常に有用であると考えられています。

問題は、「なぜJSに未定義の値があるのか」です。それが使用される主な場所:

  1. 宣言するvar x;が割り当てない場合x未定義を保持します。
  2. 関数が宣言するよりも少ない引数を受け取るとき;
  3. 存在しないオブジェクトプロパティにアクセスしたとき。

null(1)と(2)*についても同様に機能します。(3)この奇妙な結果を返す代わりに、本当にすぐに例外をスローするべきであり、そうでないという事実undefinedは、後で失敗するエラーデバッグの難しさの大きな原因です。

*:(2)は例外をスローする必要があると主張することもできますが、その場合はデフォルト/変数の引数に対して、より優れた、より明示的なメカニズムを提供する必要があります。

ただし、JavaScriptには元々例外がありませんでした。また、特定の名前のメンバーがいるかどうかをオブジェクトに問い合わせる方法はありませんでした。唯一の方法は、メンバーにアクセスして取得結果を確認することでした。これにはnullすでに目的があり、メンバーをそれに設定したい場合があるため、別の帯域外の値が必要でした。ですからundefined、あなたが指摘するように問題があります。それは、私たちが決して取り除くことができないもう1つのすばらしいJavaScriptの「機能」です。

使用されなくなったが削除したくないプロパティの値を設定解除する場合は、実際にはundefinedを使用します。代わりにnullを使用する必要がありますか?

はい。undefined他の言語が代わりに例外をスローする可能性がある場合に、シグナリングの特別な値として保持します。

null何かを設定nullするとエラーが発生する可能性がある一部のIE DOMインターフェースを除いて、通常はより優れています。多くの場合、この場合、空の文字列への設定が機能する傾向があります。


10
引数は拡張可能です。あなたは好きなだけドロップインすることができ、関数は潜在的にそれらを反復してすべてを利用することができます。オブジェクトにはいつでも新しいプロパティを割り当てることができます。これらはどちらも強力な機能ですが、必要に応じて例外をスローするとオーバーヘッドが大きくなると思います。IMO、それはトレードオフの価値があります。私は通常、より厳密な言語パラダイムでキャストするよりも、JSでの存在の確認に費やす時間を大幅に減らします。
エリック・レッペン、2014年

質問への受け入れられた回答が「これは本当に問題ではない...」で始まる方法がおかしい
Phillip

@bobinceには、JSの初期バージョンにin演算子がありませんでしたかhasOwnProperty?これはobj.hello !== undefined、オブジェクトにプロパティが存在するかどうかを確認するよりもはるかに安全だからです。
アンディ

気にしないで、私は自分の質問に答えました。MDNによれば、どちらもES3で導入されました。
アンディ

37

ここで最もよく説明されていますが、要約すると:

undefinedはタイプと値の欠如であり、nullは値の欠如です。

さらに、単純な '=='比較を実行している場合、そのとおりです。同じ結果になります。しかし、タイプと値の両方を比較する===を試してみてください。違いがわかります。


1
私の知っていることnull !== undefined-私の質問は、なぜ同じ意味論的概念を表現する2つのものが必要なのかということでした。また、あなたのリンクは「ヌルはオブジェクトである」と述べています-それは間違っています、それはプリミティブです...
クリストフ

2
それらは同じ意味論的概念ではありません。少なくとも私にとって、null値が割り当てられているプロパティと存在しないプロパティとの間には大きな違いがあります。
ダニエルシャファー

しかし、それだけです。それらは同じ意味論的概念ではありません。プログラマーの便宜として、nullは==を使用して同じことを暗黙指定します。
エディパーカー、

1
@EricElliott:typeof嘘-仕様を読むかnull、コンストラクタから戻ってみる
Christoph

5
@EricElliott:コンストラクターの戻り値は偽性とは関係ありませんが、オブジェクト性とは関係ありません。戻り値がオブジェクトの場合はそれを返します。nullまたはのようなプリミティブの場合42、戻り値を破棄し、代わりに新しく作成されたオブジェクトを返します
Christoph

17

多くの人が提案した唯一の理由(「そのような変数/プロパティがないことを意味する」)は、少なくともJavaScriptでは無効であるため、nullとの両方を使用する理由はないと思います。変数/プロパティが存在するかどうかはわかりません。undefinedundefinedundefined

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

ご覧のように、チェックfoo === undefinedしてもfoo存在するかどうかはわかりobj.bar = undefinedません。bar。。

undefined「非存在」を表すのは、JavaScript作成者の本来の意図かもしれません。しかし、実装はそのようにはなりませんでした。


1
上記のコード例でに置き換えundefinednullください。応答はすべて同じです。これがどのように質問に答えるかはわかりません。これは他の誰かの答えへのコメントを意味するものでしたか?
エリックエリオット

1
@EricElliott質問に対する私の答えは、多くの人々が提案した唯一の理由が有効ではないので、nullとの両方を持つundefined理由はないということです。
Lei Zhao

あなたはあなたの答えを編集して、実際にそれを言うべきです。もしあなたがその答えを出したなら、私は賛成票を投じたかもしれません。=)
エリックエリオット2013年

@EricElliott私はあなたが正しいと思います。回答を編集しました。ありがとう!
Lei Zhao

3
この例は、変数を割り当てなかった場合にが返されることを実際に示していますundefined。しかし、あなたがundefinedそれに割り当てた場合、それは実際にはそうではありませんundefined-それはで定義され、undefinedそれを参照しています。唯一の違いundefinedとは、nullその使用法や歴史的な目的です。どちらもアトミックです。
アレクセイコマロフ

6

両方を必要とすることは完全に可能です。たとえば、WMIをクエリする場合、クラスがnull値を持つプロパティを返すことは完全に可能です。それらは定義されており、たまたまその時点でnullを保持しているだけです。


6

JavaScript undefinedが「そのようなプロパティは存在しない」と定義しているというあなたの結論は、null「プロパティには値がないは完全に正しいます。そして、JavaScriptのように動的な言語では、それは非常に重要な違いです。ダックタイピングの使用は、存在しないプロパティと値を持たないプロパティを区別できる必要があることを意味します。これは、型情報を導出する主な手段です。静的に型付けされた言語では、nullのフィールドと存在しないフィールドの間に明確な違いがあります。JavaScriptでもこれは同じです。ただし、実行時にチェックされ、その時まで変更できます。

多くの場合、区別がぼやけているため、実装が奇妙であることに同意する必要があります。ただし、JavaScriptでは区別が重要だと思います。そして、割り当てることundefinedができることが不可欠です。

JavaScriptで書かれたオンラインRPGについてのブログ記事を少し前に読んだことを覚えています。オブジェクトがプロトタイプ(クラス、関数など)ではなく既存のインスタンスのコピーとして作成され、その後変更された例を使用しました。これundefinedにより、既存のオブジェクトを変更するときの強力さを理解できましたが、誰が書いたか思い出せません。


このRPGを共有していただけませんか?
マイケル

3

意味的には、それらは異なることを意味します。null型は、そのドメイン内に1つの値nullを持ち、プロパティにこの特定の値を割り当てることができます。未定義は、割り当てられた値がまったくないことを表します。


1
しかしundefined、プロパティへの割り当てには問題なく使用できるため、このコントラクト(undfinedそのようなプロパティがない場合にのみ返される)はプログラマが簡単に破ることができます...
Christoph

2
できます、間違いなくすべきではありません。Undefinedは、JavaScriptの例外の非常に基本的/単純化された形式として使用されます-値として使用しないで、それをいくつかのプロパティに割り当ててください!それはクレイジーな男だ。
rfunduk 2009

3

Javaプログラマーとして、未定義とnullの間には大きな違いがあると思います。JavaScriptのコーディングはそれほど多くありません。JavaScriptは強く型付けされていないためです。また、undefinedとnullの違いは、実行時に頻繁に実行される自動変換によって不明瞭になります。ところで、私はそれらの変換を頻繁に利用しています。彼らは私のJSコードをよりコンパクトで読みやすくします。

質問に答えると、未定義とは、値が設定されなかったことを意味します。実際には、これは一般にバグを指します。yourObject.propertyが未定義の場合は、何らかの理由でプロパティを設定しなかったか、まったく存在しないものを探しています。これは、複数のコーダーを使用するプロジェクトで作業する場合の実際の問題です。

nullは、「値なし」が明示的に設定されたことを意味します。実際に言えば、あなたは私にその物件について何か言っています、おそらくこの文脈では使われていない、あるいは値がまだ決定されていないということです。

Javaでは、未定義のフィールドにアクセスしようとすると、常に例外が発生します。実際、コンパイラーは、コードでこれについて警告するように作成できます。


0

この例を試してください:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

ここでは、2つの異なるタイプの非常に実際的な用途があると思います。


そしてプロトタイプでは、メンバーはnullまたは単に未定義です。
ケブ

しかし、これは誰もそれを壊そうとしない限りのみ機能しobj.userid = undefinedます- 私が設定した場合、それは失敗します-私の質問の最後の編集を参照してください
クリストフ

0

つまり、JavaScriptの動的な性質です。

後で追加できるように、物事が定義されていない場合があります。これが、JavaScriptが非常に強力で拡張性のある理由であると言えるでしょう。


これは私の質問にどのように関連していますか?
クリストフ

2
それはあなたの質問に答えるので、それは関連しています。「null」は「値がない」ことを意味する一種の「シングルトン」です。'undefined'は、何かが...衝撃的だと私に知らせています...私は知っています...定義されていません。それらは完全に異なるものです。
rfunduk 2009

0

プログラムをJavaScriptのイベントパラダイムにラップする場合、これは重要な言語機能です。

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

これは、「nothing」を使用してデフォルトのアクションを示すのとは異なるアクションを示す「nothing」を表す値が必要なデータのセットを処理する場合に非常に役立ちます。

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

上記のコードでは、nullキーワードと未定義のサーバーが非常に明確で異なる目的に使用されています。undefinedを返すfilter_func_ptオブジェクトで見つからないルックアップは、プロパティをそのまま返されるオブジェクトに追加することを意味します。一方、null値は、値が保留され、追加されないことを示し、これにtrue値が存在することを示します。 caseは、値をretオブジェクトに追加する前に値を変換するために使用される関数を表します。


この例は人為的であり、少し無意味です。Nullは意図をまったく明確にしません-むしろそれを覆い隠します。より明確な文字列を使用して、意味を明確にすることもできます。'withhold'または 'strip'のように、関数タイプについてより明確にして、実際に関数の存在を確認することもできます。
エリックエリオット

0

nullは美しい

他のすべての種類のライブスクリプトと同様に。

cite:JavaScriptには、基本的に「存在しない」と言う2つの値があります-未定義とnullです。

なぜ間違ったことを言いたいのですか?

0」が「空の番号」であるのと同じように、「null」「空のオブジェクトです。0、何もありません-まだ、数値のタイプとして存在します。 nullももちろん空ですが、「それは」であり、オブジェクト型の明確に定義されたものです

「タイプ」としてではなく、そうでない場合にこれらのことを話すのが一般的です。実際、それらは「カテゴリー」です。しかし、これで終わりです。

したがって、「null」は種類のないオブジェクトのタイプであると言ってそれに固執します。そして「null」は「私は非常に存在します[!]ですが、私のような内容はありません」と言います。

一方、未定義のタイプ及び種類の両方欠い未定義は、そのタイプの定義であることを起こるが。型の未定義の型は、その独特の類型になります。ある種の[「何もない」は存在しますが、「何もない」とどのように定義しますか?]質問。

cite:undefinedもnullもコンストラクタ関数から返すことができます。どちらも空のオブジェクトへのコンバータになるためです。

あなたはなんとか間違ったことをもう一度言うことができました。もちろん、「未定義」はオブジェクトではなく、人間が理解できる単純なトークンです。しかし、そのnullとは対照的です-そしてそれはあなたに言っています:そのTypeは正しいですが、あなたが探しているKindはその中に含まれていません、または少なくとも-現在のところありません。後でオブジェクトを\割り当てるときに私たちを訪ねてください。

cite:私が考えることができる唯一の真の違いは、1つはNaNに評価され、もう1つは数値コンテキストで0に評価されることです。

前述のように、それはそれらのコアの区別の全体のポイントを作ります:undefinedはプレーントークンであり、それはその遠い親戚:文字列と同じ「遺伝的」素材で構成されるため、[+ undefined]操作はそれをダック変換しますNaN、同様にnullはもちろん、代わりにそれ自体を正しい種類の0 \ Numberにモーフします。未定義とは対照的に、文字列にモーフします(!空ではありません)。これが、NaNを生成する理由です。代わりに。場所:+ undefined >> + "undefined" >> NaN。数値コンテキストは明示的な値を期待するため。

ブールコンテキストは参照を期待していますが、変換するものは何も見つからず、 'false'を返します。

さっそく切りましょう...

cite:では、もう一度:undefinedとnullの別々の値の実際的な用途は何ですか?

私はあなたに二つの経験的な例だけを与えようとします、そして十分であることを望みます

oElement.onclick >> null

//は、プロパティが存在することを意味します。その期待値はType:Objectであり、そのoElementは「onclick」イベントをサポートしています!

oElement.innerText >> ""

//意味-プロパティが存在する; その期待値はType:Stringです。これは、oElementが「innerText」プロパティをサポートすることを意味します。

どちらの場合も、「未定義」を受け取った場合は、プロパティが存在しないことを意味します。はサポートされていないか、間違った(UAベンダー)実装があります。

霜を降りて楽しんでください。


あなたの投稿を破壊してはいけません。投稿を削除したい場合は、このコメントのすぐ上にある[削除]ボタンを使用して削除してください。
Michael Petrotta

削除ボタンはありませんが、表示されている場合はクリックしてください。

0

未定義とnullに関する素晴らしい議論を読んだ後、グーグルで少し検索すると、Mozillaドキュメンテーション https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/nullに移動しました nullがしばしばある-それは言及されていますオブジェクトが期待できる場所で検索されたが、関連するオブジェクトがない。

Is n'tはNullオブジェクトパターンに似ています https://en.wikipedia.org/wiki/Null_object_pattern

だから私はこれがNullデータ型を持つことは理にかなっていると思います。

ドキュメントはtypeof null // "オブジェクト"とも呼ばれます(従来の理由から "null"ではありません)

従来の理由がわからない

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.