web-dev-qa-db-ja.com

ES6でパラメータとしてNULLを渡すと、デフォルトパラメータが提供されたときにそのパラメータが使用されません

ES6のパラメーターとしてnullを渡すと、デフォルトのパラメーターが提供されたときに使用されないという既知の理由はありますか?

function sayHello(name = "World") {
    console.log("Hello, " + name + "!");
}

sayHello("Jim");     // Hello, Jim!
sayHello(undefined); // Hello, World!
sayHello(null);      // Hello, null!
45
aus_lacy

これはそれほど明白ではありません

undefinednullと完全に異なる理由についてのコメントを読んだことがあり、それがデフォルトパラメータの現在の動作を説明している理由です。

関数を持っているときは、未定義のを明示的に渡すとデフォルト値の置換がトリガーされないと主張できます。

_const f = (x = 'default') => console.log(x);
_

次のように実行すると_"default"_が出力されます。

_f();
_

しかし、明示的に次のように実行したときに_"undefined"_を出力したいと思います。

_f(undefined);
_

さもなければ、なぜ最初にf(undefined)を使用するのでしょうか?ここでの私の意図は明らかに、それを除外するのではなく、何らかの議論を提供することです。

反対の例

ここで、この機能を検討してください。

_const g = (...a) => console.log(JSON.stringify(a));
_

私がそれを使用するとき:

_g();
_

取得:_[]_

ただし、次のように使用する場合:

_g(undefined);
_

取得:_[null]_

次のことを明確に示しています。

  1. undefinedを渡すことは、引数をまったく渡さないことと同じではありません
  2. 時々nullundefinedの代わりにデフォルト値になります

TC39の決定

デフォルトパラメータの現在の動作に関する背景は、TC39による2012年7月24日のミーティングノートで見ることができます。

ちなみに、最初に明示的にundefinedを渡すとdid notが最初のドラフトのデフォルト値をトリガーし、それを行うべきかどうかについての議論があったことを示しています。ご覧のとおり、現在の動作はTC39のメンバーにとってそれほど明白ではありませんでした。

他の言語

そうは言っても、何がデフォルト値の置換をトリガーすべきか、何をトリガーすべきではないかの決定は、その日の終わりには完全に任意です。別々にundefinednullを用意しても、考えてみると非常に奇妙に思えます。一部の言語はundefinedのみ(Perlのundefなど)、一部の言語はnullのみ(Javaなど)、一部の言語ではfalseと同等または空のリストまたは配列を使用しますそれ(空のリストまたは_#f_(false)を持つことができるSchemeのように、空のリストとfalse値の両方から区別されるnullに相当するものはありません) nullfalse、またはundefinedと同等のものもあります(trueおよびfalseの代わりに整数を使用するCなど、実際には通常のNULLポインターアドレス0を指すポインター-nullポインターをテストするコードによってマップされた場合でも、そのアドレスにアクセスできなくなります。

できること

これで、nullをデフォルト値に置き換える必要があることを理解できました。残念ながら、これはデフォルトの動作ではありませんが、次のような簡単な関数を作成できます。

_const N = f => (...a) => f(...a.map(v => (v === null ? undefined : v)));
_

これで、null値の代わりにデフォルトを使用するたびに、このように使用できます。例えば。上記の例のいずれかからこの関数を使用している場合:

_const f = (x = 'default') => console.log(x);
_

f()およびf(undefined)に対しては_"default"_を出力しますが、f(null)に対しては出力しません。ただし、上記で定義したN関数を使用して、次のようにf関数を定義すると、

_const f = N((x = 'default') => console.log(x));
_

現在f()f(undefined)が、f(null)も_"default"_を出力します。

多少異なる動作が必要な場合、例えば空の文字列をデフォルト値に置き換える-存在しないのではなく空の文字列に設定されることがある環境変数に便利で、次を使用できます。

_const N = f => (...a) => f(...a.map(v => (v === '' ? undefined : v)));
_

すべての偽の値を置換する場合は、次のように使用できます。

_const N = f => (...a) => f(...a.map(v => (v || undefined)));
_

空のオブジェクトを置き換える場合は、次を使用できます。

_const N = f => (...a) => f(...a.map(v => (Object.keys(v).length ? v : undefined)));
_

等々...

結論

重要なのは、それがあなたのコードであり、関数のAPIとは何か、そしてデフォルト値がどのように機能するかを知っているということです。幸いなことに、JavaScriptは強力な機能を備えているため、必要なものを簡単に実現できます(いわば、それがデフォルト値のデフォルトの動作ではない場合でも)。

23
rsp

これが、仕様でデフォルトパラメータが定義されている方法です。 [〜#〜] mdn [〜#〜] :(エンファシス鉱山)を参照

デフォルト関数パラメーターを使用すると、値なしまたは未定義が渡された場合に、デフォルト値で仮パラメーターを初期化できます。

nullno valueでもundefinedでもないため、デフォルトの初期化をトリガーしません。

29
doldt

nullは、使用されるデフォルト値をトリガーしない値です。引数がundefinedの場合、デフォルト値が使用されます。

1
taxicala