JavaScriptでundefinedではなくnullを使用する理由は何ですか?


103

私は長い間JavaScriptを作成してきましたが、を使用する理由がありませんでしたnull。それundefinedは常に望ましいようで、プログラム的に同じ目的を果たします。のnull代わりに使用する実際的な理由は何undefinedですか?



まあ、document.getElementById()それは返すことができるnullundefinedそうではないようなメソッドがあるので、それらの場合、なぜ戻りをテストするのundefinedですか?(確かに、==ではなくを使用すれば機能します===が、それでもなぜ故意に間違ったものをテストするのでしょうか?)
nnnnnn

予測可能なタイプがあると便利な場合があり、これはどちらか一方を使用することを考える上で役立ちます。オブジェクトが常に返される場合、必要に応じて、または設計上必要な場合は、不正な結果にはnullを使用します(などdocument.getElementById('does-not-exist'))。変数var a;と関数の戻り値のデフォルトは未定義です。以前はnullがグローバルスコープにあったため、これを使用すると実行が遅くなり、参照を解放するために他の偽の型(false、 ''、0)を優先するようになりました。私は、他にやむを得ない理由がない限り、個人的にはnullを避けています。
ジムモント2016

回答:


59

Nullとundefinedは、本質的に同じことを意味する2つの異なる値です。唯一の違いはである規則あなたがそれらを使用する方法のあなたのシステム。一部の人が言及したように、一部の人々は「オブジェクトがない」という意味でnullを使用しますが、未定義はオブジェクトが予期されていない(またはエラーが発生した)ことを意味します。それに関する私の問題は、完全に恣意的であり、完全に不必要です。

つまり、1つの大きな違いがあります。初期化されていない変数(特に、引数が渡されなかった関数パラメーターを含む)は常に未定義です。

これが私のコードで、私が制御しない何かがnullを返さない限り(たとえば、正規表現マッチング)、nullを使用しない理由です。これの美しさは、それが物事を多く単純化することです。x ===未定義かどうかを確認する必要はありません|| x === null。また、==を使用する習慣がある場合や、単にif(x)... やめて !x空の文字列、0、null、NaNに対してtrueと評価されます-つまり、おそらく望まないものです。ひどくないJavaScriptを作成する場合は、常に等号===を使用し、nullを使用しないでください(代わりにundefinedを使用してください)。それはあなたの人生をより簡単にします。


137
私はこれに同意しません。Nullは、プログラムで空のものを定義するために使用されます。未定義とは、参照が存在しないことを意味します。null値には、 "nothing"への参照が定義されています。オブジェクトの存在しないプロパティを呼び出すと、未定義になります。そのプロパティを意図的に空にする場合は、それがnullである必要があります。多くのJavaScriptライブラリはこのように機能します。
com2ghz 2016

6
@ com2ghzあなたが説明するのは、多くの哲学の1つです。多くのjsライブラリは実際にそのように機能します。また、多くはそのように機能しません。JavaScriptでは、nullの場合と同じように、明示的な未定義の値をオブジェクトまたは配列に簡単に格納できます。両方の意味は、完全におよび完全にコンテキストに依存しています。つまり、あなたが彼らに何を意味するかを意味します。
BT

3
そのため、JSは恐ろしい言語です。あなたが言うように、多くのライブラリーには独自の哲学がありますが、1つのプロジェクトに多くのライブラリーを含めます。そのため、これらのライブラリの多くの規則に遭遇します。さまざまな偽のチェックを何回行う必要がありますか。nullオブジェクトを文字列に連結して「null」を文字列として取得するのはこれが最後ではありません。または、数値として0を渡し、IFステートメントが処理する理由がtと偽であると疑問に思います。
com2ghz 2016

2
@ com2ghzでは、JSにはnullと未定義の両方があるため、JSは恐ろしい言語ですか?私はすべての主要言語で何十もの悪い言語決定を数えることができます、jsはここに例外ではありません。文字通り、コードで偽のチェックを使用する必要はありませんし、使用したくないので、常に===またはを使用します!==。JSの使い方を知っていれば、JSは素晴らしく表現力豊かな言語です。
BT

6
正しい。JSの初期バージョンには、または演算子がなかったため、null/のundefined二分法が必要であることを知りました。今はそうなのですが、ES6や私が見たES7の提案のなかで廃止されなかった理由がよくわかりません。hasOwnPropertyin
アンディ

86

私は実際に答えを持っていますが、に応じませんニコラスC. Zakas、彼の本のページ30 のWeb開発者のための専門のJavaScript

後でオブジェクトを保持するための変数を定義するときは、null他のものとは対照的に変数を初期化することをお勧めします。そうnullすれば、値を明示的にチェックして、変数が後でオブジェクト参照で埋められているかどうかを判断できます


8
+1はい、同意し、常に変数をnullに初期化することを忘れないようにしています。そして、私は(かなり)undefinedそれが災害が起こったことを意味すると確信しています。ちょうど私見。
ピートウィルソン

9
@ピート-しかし、それはあなたに「災害」について何も伝えないので、要点は何ですか?そして、関数が規則に従うことがわかっている場合にのみ、その仮定を行うことができます。
RobG、2011

7
一方、変数を初期化var myVar;して値undefinedを明示的に確認し、後でオブジェクト参照が入力されているかどうかを確認することもできます。私のポイントは、これは完全に学術的であるということです。あなたはどちらの方法でもそれを行うことができ、一方を他方に助言する人は誰でも自分たちの慣習を推進するだけです。
thdoan 2015年

1
(15年前にJavaScriptを使い始めて以来)私が抱えている唯一の問題は、テストundefinedやテストを頻繁に行わなければならないことnullです。これはまだ本当に迷惑です。null余分なnullテストの数を減らすためだけに変数を割り当てることは避けます。
Gマン

4
@GMan-これは==(とは対照的に===)比較が意味をなす唯一の場所です:(v == nullまたはv == undefined)はnullまたは未定義をチェックします。
リック・ラブ

14

一日の終わりには、両方のためnullundefined同じ値に強制変換(Boolean(undefined) === false && Boolean(null) === false)、あなたが技術的に仕事を得るためにいずれかを使用することができます。しかし、IMOには正しい方法があります。

  1. の使用はundefinedJavaScriptコンパイラに任せてください。

    undefined参照を指さない変数を記述するために使用されます。これは、JSコンパイラーが処理します。コンパイル時に、JSエンジンはすべての巻き上げ変数の値をに設定しますundefined。エンジンがコードと値を利用できるようになると、エンジンはそれぞれの値をそれぞれの変数に割り当てます。値が見つからなかった変数の場合、変数はプリミティブへの参照を維持し続けundefinedます。

  2. 変数の値を「値なし」として明示的に示す場合にのみ、nullを使用します。

    @ com2gzが述べるnullように、プログラムで空の何かを定義するために使用されます。undefined参照が存在しないことを意味します。null値が「何」に定義された参照を持っています。オブジェクトの存在しないプロパティを呼び出す場合は、を取得しundefinedます。そのプロパティを意図的に空にする場合は、それが意図的なものであるnullことを知っている必要があります。

TLDR; undefinedプリミティブを使用しないでください。これは、割り当てなしで変数を宣言した場合、または参照のないオブジェクトのプロパティにアクセスしようとした場合に、JSコンパイラーが自動的に設定する値です。一方、null意図的に変数に「値なし」を設定する場合にのみ使用します。

私は明示的に何かを未定義に設定したことはありません(私が操作した多くのコードベースでこれに遭遇したことはありません)。また、私はめったに使用しませんnull。私が使用するのnullは、関数の引数の値を値がないものとして示したい場合だけです。つまり、

function printArguments(a,b) {
  console.log(a,b);
}

printArguments(null, " hello") // logs: null hello

これが選択された答えであるはずです
アラバウディ

13

undefinedは、物事の概念が存在しない場所です。タイプはなく、そのスコープ内で以前に参照されたことはありません。nullは、存在することがわかっている場所ですが、値はありません。


4
値を割り当てようとしたが失敗し、代わりにundefinedが割り当てられたかどうかをどのようにして知ることができますか?
RobG

11

誰もがコーディングし、独自の内部セマンティクスの独自の方法がありますが、長年にわたって、私はこれは私がこの質問を人々与えることが最も直感的なアドバイスであることが判明している:疑いで、JavaScriptは何をやります

jQueryプラグインのオプションなどのオブジェクトプロパティで作業しているとしましょう... JavaScriptがまだ定義されていないプロパティをどのような値にするかを自問してください-答えはundefinedです。したがって、このコンテキストでは、JavaScriptと整合するように「未定義」でこれらのタイプのものを初期化します(変数の場合は、のvar myVar;代わりに行うことができますvar myVar = undefined;)。

ここで、DOM操作を行っているとしましょう... JavaScriptが存在しない要素に割り当てる値は何ですか?答えはnullです。これは、DOMに関連する要素、ドキュメントフラグメントなどへの参照を後で保持するプレースホルダー変数を作成する場合に初期化する値です。

JSONを使用している場合は、特別なケースを作成する必要があります。未定義のプロパティ値の場合は、に設定する""null、の値がundefined適切なJSON形式と見なされないためです。

これは以前のポスターが表明したように、言ってあなたはあなたがものを初期化していることを発見した場合、nullまたはundefinedより多くのブルームーンでは何度も、そして多分あなたは、あなたのアプリのコーディングに取り掛かる方法を再考する必要があります。


:これは良い姿勢ですが、私はこの答えを追加したいと思いstackoverflow.com/a/37980662/883303
フレデリックKrautwald

@FrederikKrautwaldリンクに感謝-それは非常に明確な描写です。
thdoan

10

ここで提案されている規約を採用するかもしれませんが、実際に正当な理由はありません。意味のあるほど一貫して使用されていません。

規約を有効にするには、呼び出された関数が規約に従うことを最初に知る必要があります。次に、戻り値を明示的にテストして、何をするかを決定する必要があります。あなたが得る場合は未定義、あなたは何らかのエラーが発生したと仮定することができますと呼ばれる機能が知っていたことを。しかし、エラーが発生し、関数がそれを知っていて、それをより広い環境に送信すると便利な場合は、エラーオブジェクトを使用しませんか?つまり、エラーをスローしますか?

つまり、結局のところ、この規約は、単純な環境での非常に小さなプログラム以外には何の役にも立ちません。


3

で有用な性質ヌルという未定義の資格はありません。

> null + 3
3
> undefined + 3
NaN

null数値を「オフ」にする場合、または数値を初期化する場合に使用します。私の最後の使用はcss変換の操作でした:

const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });

// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });

このプロパティ使用する必要があるかどうかわからない...


2

DOMノードと要素は未定義ではありませんが、nullの場合があります。

  • 要素の最後の子のnextSiblingはnullです。

  • 最初の子のpreviousSiblingはnullです。

  • 要素がドキュメントに存在しない場合、document.getElementById参照はnullです。

しかし、これらのいずれの場合も、値は未定義ではありません。そこにはノードがありません。


説明ありがとう。私にとって、これは直感に反することはできません。
tomekwi 2014

それは本当にあなたがチェックしようとしているものに依存します。たとえば、「myVar」という名前のグローバル変数が存在するかどうかを確認するwindow.myVar場合、存在しない場合は「undefined」を返します。JavaScriptで 'undefined'を返すものはたくさんありますが、 'null'を返すものはたくさんあります-それはすべてコンテキストに依存します。
thdoan 2015年

2

オブジェクトをに初期化することは問題ないと言う人もいますnull。破壊的な引数のデフォルトはで機能しないことを指摘したかっただけnullです。例えば:

const test = ({ name } = {}) => {
  console.log(name)
}

test() // logs undefined
test(null) // throws error

これには、頻繁に発生する可能性がある関数を呼び出すnullチェックを実行する必要があります。


1

私は今、この正確な質問に取り組んでおり、次の哲学を見ています。

  1. 結果を返すことを目的とした関数は、結果が見つからない場合はnullを返す必要があります。
  2. 結果を返すことを目的としていない関数は、暗黙的に未定義を返します。

私にとって、この質問は重要です。結果を返す関数を呼び出す人は誰でも、未定義かnullかをテストするかどうかについて質問がないはずです。

この回答では、次のことは取り上げません。

  1. nullと未定義のプロパティ値
  2. 関数内の変数がnullか未定義か

私の意見では、変数は独自のビジネスであり、APIの一部ではありません。オブジェクト指向システムのプロパティは定義されているため、定義されていない場合とは異なる値で定義する必要があります(定義されている場合はnull、定義されていない場合は、オブジェクトにないものにアクセスするときに取得します)。


1

理由は次のとおりです。var undefined = 1 正当なJavaScript var null = 1ですが、構文エラーです。違いは、それnullは言語のキーワードundefinedですが、何らかの理由でそうではありません。

コードがundefinedそれがキーワードであるかのように比較に依存している場合(if (foo == undefined)-作成するのは非常に簡単な間違いです)、その名前で変数を定義した人がいないためにのみ機能します。そのコードはすべて、誰かが誤ってまたは悪意を持ってその名前のグローバル変数を定義することに対して脆弱です。もちろん、JavaScriptで誤ってグローバル変数を定義することはまったく不可能であることは誰もが知っています...


1
void 0未定義の代わりに使用します。
Frederik Krautwald、2016年

1

特定のjavascriptライブラリを使用すると、nullおよびundefinedが意図しない結果をもたらす可能性があることを追加したいだけです。

たとえばget、3番目の引数としてデフォルト値を受け入れるlodashの関数:

const user = {
  address: {
    block: null,
    unit: undefined,
  }
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'

別の例:ReactでdefaultPropsを使用する場合、プロパティが渡さnullれると、nullは定義された値として解釈されるため、デフォルトのプロパティは使用されません。例えば

class MyComponent extends React.Component {
   static defaultProps = {
      callback: () => {console.log('COMPONENT MOUNTED')},
   }
   componentDidMount() {
      this.props.callback();
   }
}
//in some other component
<MyComponent />   // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/>   // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/>   // Console WILL print "COMPONENT MOUNTED"

0

nullまたはundefinedの使用が不要であることにまったく同意しません。undefinedは、プロトタイプチェーンプロセス全体を維持するものです。したがって、nullのみのコンパイラは、このプロパティがnullに等しいかどうか、またはエンドポイントプロトタイプで定義されていないかどうかをチェックできません。他の動的型付き言語(Pythonの場合)では、定義されていないプロパティにアクセスしたい場合に例外がスローされますが、プロトタイプベースの言語の場合、コンパイラーは親プロトタイプもチェックする必要があります。

nullを使用することの全体的な意味は、シングルトンで空の意味を持つオブジェクトに変数またはプロパティをバインドすることであり、nullの使用にはパフォーマンス上の目的もあります。この2つのコードは実行時間が異なります。

var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p1();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)

var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p2();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p; 
});
big_array.reduce((sum, p)=> sum + p.value, 0)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.