web-dev-qa-db-ja.com

JavaScriptで未定義の代わりにnullを使用する理由は何ですか?

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

91
Jimmy Cuadra

Nullとundefinedは、本質的に同じことを意味する2つの異なる値です。唯一の違いは、yourシステムでの使用方法のconventionsにあります。一部の人が述べたように、一部の人々は「オブジェクトなし」を意味するためにnullを使用しますが、未定義はオブジェクトが予期されていないことを意味しますそれに関する私の問題は、完全にarbitrary意的であり、完全に不必要です。

ただし、1つの大きな違いがあります。初期化されていない変数(引数が渡されなかった関数パラメーターなどを含む)はalways undefinedです。

私のコードでは、never制御しないものがnullを返さない限り、nullを使用する理由です(たとえば、正規表現の一致)。これの美しさは、物事を非常に単純化することです。 x === undefined ||かどうかを確認する必要はありません。 x === null。また、==またはif(x)...のようなものを使用する習慣がある場合。やめて!xは、空の文字列、0、null、NaNの場合にtrueと評価されます。ひどくはないjavascriptを書きたい場合は、常に三重の等しい===を使用し、nullを使用しないでください(代わりにundefinedを使用してください)。それはあなたの人生をより楽にします。

40
B T

答えはありませんが、Nicholas C. Zakas、彼の本の30ページ "Web開発者向けのプロフェッショナルJavaScript "

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

76
bbg

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

規約を有効にするには、まず、呼び出された関数が規約に従っていることを知っておく必要があります。次に、返された値を明示的にテストし、何をすべきかを決定する必要があります。 ndefinedを取得した場合、何らかのエラーが発生したと想定できます呼び出された関数が知っていた。しかし、エラーが発生し、関数がそれを知っていて、それをより広い環境に送信することが有用な場合、エラーオブジェクトを使用しないのはなぜですか?つまり、エラーをスローしますか?

そのため、結局のところ、この規則は、単純な環境での非常に小さなプログラム以外では実質的に役に立ちません。

10
RobG

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

10
Alex Shapovalov

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

JQueryプラグインのオプションなどのオブジェクトプロパティを操作しているとしましょう。JavaScriptがまだ定義されていないプロパティに与える値を自問してください。答えはundefinedです。そのため、このコンテキストでは、これらのタイプのことを 'undefined'で初期化して、JavaScriptとの一貫性を保ちます(変数の場合、var myVar;の代わりにvar myVar = undefined;を実行できます)。

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

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

これにより、前のポスターが表明したように、ブルームーンでnullまたはundefinedで複数のものを初期化していることがわかった場合、アプリのコーディング方法を再検討する必要があります。

9
thdoan

一日の終わりには、nullundefinedの両方が同じ値(Boolean(undefined) === false && Boolean(null) === false)に強制されるため、技術的にどちらかを使用してジョブを完了することができます。しかし、正しい方法があります、IMO。

  1. undefinedの使用はJavaScriptコンパイラーに任せます。

    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
6
Govind Rai

nullの便利なプロパティndefinedは条件を満たしていません:

> 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); });

私がshouldを使用しているかどうかわからない.

2
Faccion

いくつかは、オブジェクトをnullに初期化してもよいと言っています。 nullでは引数のデフォルトの構造化が機能しないことを指摘したかっただけです。例えば:

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

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

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

2
Matt Way

理由は次のとおりです。_var undefined = 1_は正当なjavascriptですが、_var null = 1_は構文エラーです。違いは、nullは言語キーワードですが、undefinedは何らかの理由でそうではないということです。

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

2
Joel Mueller

DOMのノードと要素は未定義ではありませんが、nullでもかまいません。

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

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

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

しかし、これらのケースでは値ndefined;はありません。そこにノードはありません。

2
kennebec

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

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

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

この答えは対処しようとしません:

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

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

1
Michael

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

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

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"
1
lilbitofchee

Nullまたは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)
1