JavaScriptに「null合体」演算子はありますか?


1381

JavaScriptにnull合体演算子はありますか?

たとえば、C#では、これを行うことができます。

String someString = null;
var whatIWant = someString ?? "Cookies!";

私がJavaScriptについて理解できる最善の近似は、条件演算子を使用することです。

var someString = null;
var whatIWant = someString ? someString : 'Cookies!';

それはちょっとイッキーな私見です。もっと上手にできますか?


31
2018年のメモ: x ?? y構文は現在、ステージ1のプロポーザルステータスにあります- 無効な合体
Aprillion

2
現在、この正確な構文を組み込んだBabelプラグインがあります。
ジョナサンスディアマン

10
2019からのメモ:現在はステージ3ステータスです!
Daniel Schaffer

3
2020年1月からのメモ:Nullish合体演算子はFirefox 72でネイティブに利用できますが、オプションの連鎖演算子はまだ利用できません。
Kanos

4
空っぽの合体演算子(x ?? y)とオプションの連鎖演算子(user.address?.street)がどちらもステージ4になりました。これが何を意味するかについての適切な説明は次のとおりです。2ality.com / 2015 / 11 / tc39-process.html#stage-4%3A-finished
マスドットネット

回答:


2135

更新

JavaScriptは、無効な合体演算子(??)をサポートするようになりました。左側のオペランドがnullorのundefined場合は右側のオペランドを返し、それ以外の場合は左側のオペランドを返します。

使用する前に互換性を確認してください。


C#のnull結合演算子(??)に相当するJavaScript では、論理OR(||)を使用しています。

var whatIWant = someString || "Cookies!";

振る舞いがC#の振る舞いと一致しない場合があります(以下で明確化)が、これはJavaScriptでデフォルト/代替値を割り当てる一般的で簡潔な方法です。


明確化

最初のオペランドのタイプに関係なく、それをブール値にキャストすると結果がfalseになる場合、割り当てでは2番目のオペランドが使用されます。以下のすべてのケースに注意してください。

alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)

これの意味は:

var whatIWant = null || new ShinyObject(); // is a new shiny object
var whatIWant = undefined || "well defined"; // is "well defined"
var whatIWant = 0 || 42; // is 42
var whatIWant = "" || "a million bucks"; // is "a million bucks"
var whatIWant = "false" || "no way"; // is "false"

48
「false」、「undefined」、「null」、「0」、「empty」、「deleted」などの文字列は、空ではない文字列であるため、すべてtrueです。
いくつかの

4
これを明確にする必要があります。「」はnullではありませんが、誤ったものと見なされます。したがって、nullの値をチェックしていて、それが ""である場合は、このテストに正しく合格しません。
ScottKoon 2010

99
注目すべきは||、最初の「真」の値または最後の「偽」の値(真に評価できないものがある場合)を&&返し、逆の方法で機能することです:最後の真の値または最初の偽の値を返します。
ジャスティンジョンソン

19
まだ気にする人には参考までに。型のコンストラクタを使用して宣言すると、0と空の文字列はnullと同じように評価されます。var whatIWant = new Number(0) || 42; // is Number {[[PrimitiveValue]]: 0} var whatIWant = new String("") || "a million bucks"; // is String {length: 0, [[PrimitiveValue]]: ""}
Kevin Heidt 2014年

5
@LuisAntonioPestana var value = myObj && myObj.property || ''''、myObjまたはmyObj.propertyのいずれかが偽の場合にフォールバックします。
Ates Goral 2017年

77
function coalesce() {
    var len = arguments.length;
    for (var i=0; i<len; i++) {
        if (arguments[i] !== null && arguments[i] !== undefined) {
            return arguments[i];
        }
    }
    return null;
}

var xyz = {};
xyz.val = coalesce(null, undefined, xyz.val, 5);

// xyz.val now contains 5

このソリューションはSQLの合体関数のように機能し、任意の数の引数を受け入れ、値がない場合はnullを返します。C#のように動作しますか?""、false、および0はNOT NULLと見なされるため、実際の値としてカウントされるという意味で演算子。あなたが.netのバックグラウンドから来ているなら、これは最も自然な感じの解決策です。


8
for(var i in arguments)よると、繰り返し順序を保証するものではありませんMDNJavaScriptのFor…Inループが配列に推奨されない理由も参照してくださいそして、配列反復で「for ... in」を使用するのはなぜそんなに悪い考えなのでしょうか。
MvG 2015

13
このような追加が遅いことをお詫びしますが、完全を期すために、このソリューションには短絡評価がないという警告があります。引数が関数呼び出しの場合は、値が返されるかどうかに関係なくすべて評価されます。これは、論理OR演算子の動作とは異なるため、注目に値します。
Haravikk

63

はい、間もなく登場します。参照してくださいここに提案し、ここでの実施状況を

次のようになります。

x ?? y

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false

2
現在はステージ3で、次のTypeScriptリリースの予定です!github.com/microsoft/TypeScript/issues/26578
lautaro.dragan

1
空っぽの合体演算子(x ?? y)とオプションの連鎖演算子(user.address?.street)がどちらもステージ4になりました。これが何を意味するかについての適切な説明は次のとおりです。2ality.com / 2015 / 11 / tc39-process.html#stage-4%3A-finished
マスドットネット

45

場合は||C#のの代替として??あなたのケースでは良い十分ではありません、それは空の文字列とゼロを飲み込んだので、あなたは常に自分自身の関数を書くことができます。

 function $N(value, ifnull) {
    if (value === null || value === undefined)
      return ifnull;
    return value;
 }

 var whatIWant = $N(someString, 'Cookies!');

1
alert(null || '')は空の文字列を警告しますが、私は実際にそのalert( '' || 'blah')が空の文字列ではなくblahを警告するのが好きだと思います。(+1)
ダニエルシャファー

1
私は実際にfalse、(厳密に)null / undefinedの場合に返される関数を定義することを好むと思いますtrue。多くのネストされた関数呼び出しよりも読みやすくなる可能性があります。たとえば$N(a) || $N(b) || $N(c) || d、より読みやすいです$N($N($N(a, b), c), d)
ボブ

ブレントラーセンのソリューションはより一般的です
Assimilater

if .. return .. else ... return三元の場合に最適です。 return (value === null || value === void 0) ? ifnull : value;
アレックスマクミラン

15

ここでは、の可能性について誰も言及しNaNていません。それで、2セント追加すると思いました。

指定されたコードの場合:

var a,
    b = null,
    c = parseInt('Not a number'),
    d = 0,
    e = '',
    f = 1
;

||演算子を使用すると、最初の偽でない値が得られます。

var result = a || b || c || d || e || f; // result === 1

ここ掲載されている一般的な合体方法を使用すると、次cの値を持つが得られます。NaN

var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN'

これらのどちらも私には正しくないようです。あなた自身の世界とは異なる可能性のある合体ロジックの私自身の小さな世界では、未定義、null、およびNaNはすべて「nullっぽい」と見なします。したがって、d合体メソッドから(ゼロに)戻ることを期待します。

誰かの脳が私のように機能し、を除外したいNaN場合、このメソッドはそれを達成します:

function coalesce() {
    var i, undefined, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg !== null && arg !== undefined
            && (typeof arg !== 'number' || arg.toString() !== 'NaN') ) {
            return arg;
        }
    }
    return null;
}

コードをできるだけ短くしたい人や、明確さの少しの不足を気にしない人のために、@ impinballが提案するようにこれを使用することもできます。これは、NaNがNaNに等しくなることはないという事実を利用しています。詳しくは、こちらをご覧ください。なぜNaNはNaNと等しくないのですか?

function coalesce() {
    var i, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg != null && arg === arg ) { //arg === arg is false for NaN
            return arg;
        }
    }
    return null;
}

ベストプラクティス-引数を配列のように扱い、NaN!== NaN(typeof+ num.toString() === 'NaN'は冗長です)を利用し、現在の引数をではなく変数に格納しますarguments[i]
Isiah Meadows

@impinball、提案された編集は機能せず、テストケースから0(ゼロ)ではなくNaNを返します。またはで!== 'number'ないことをすでに評価しているので、技術的にチェックを削除することができますが、これには、このコードを読んでいる人には非常に明確で、順序に関係なく条件が機能するという利点があります。あなたの他の提案はコードを少し短くするので、私はそれらを使用します。nullundefined
Kevin Nelson、

2
@impinball、私はあなたの提案された編集であなたのバグを見つけました、あなたはそれをのままにしましたarg !== arg、しかしあなたはそれがそうである必要がありますarg === arg... しかし、それはあなたが何をしているのかが非常に不明確であるという欠点がarg === argあります... コードを調べて冗長であると考える次の人によって削除されないようにコードにコメントが必要です...しかし私はそれを上げますとにかく。
Kevin Nelson

良いキャッチ。ちなみに、これはNaN!== NaNという事実を利用してNaNをチェックする高速な方法です。必要に応じて、それを説明できます。
Isiah Meadows

1
「数値ではない」のチェックは組み込み関数で置き換えることができます:isNaN()
Yury Kozlov

5

JavaScript固有のnullの定義に注意してください。JavaScriptの「値なし」には2つの定義があります。1. Null:変数がnullの場合、データは含まれていませんが、変数はすでにコードで定義されています。このような:

var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts

そのような場合、変数のタイプは実際にはオブジェクトです。試して。

window.alert(typeof myEmptyValue); // prints Object
  1. 未定義:変数がコード内で以前に定義されておらず、期待どおりに値が含まれていない場合。このような:

    if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }
    // alerts

そのような場合、変数のタイプは「未定義」です。

タイプ変換比較演算子(==)を使用する場合、JavaScriptはこれらの両方の空の値に対して同等に機能します。それらを区別するには、常に型限定比較演算子(===)を使用します。


1
実際には、nullは値です。これは、Object型の特別な値です。nullに設定されている変数は、データが含まれていることを意味し、データはnullオブジェクトへの参照です。変数は、コードで未定義の値で定義できます。これは、宣言されていない変数と同じではありません。
Ates Goral

宣言されている変数と宣言されていない変数の実際の違い:alert(window.test)/ * undefined * /; alert( "test" in window)/ * false * /; window.test = undefined; alert(window.test)/ * undefined * /; alert( "test" in window)/ * true * /; for(var p in window){/ * p can be "test" * /}
Ates Goral

1
ただし(少し逆説的)未定義の値で変数を定義できますvar u = undefined;
Serge

@AtesGoral re null。あなたの言うことは真実ですが、慣例により、「null」は「(有用な)データがないこと」を表します。したがって、「データなし」と見なされます。そして、これが「nullの合体演算子」に関する質問への回答であることを忘れないでください。このコンテキストでは、nullは、内部的にどのように表現されているかに関係なく、「データなし」として確実に扱われます。
ToolmakerSteve

4

説明を読んだ後、@ Ates Goralの答えは、JavaScriptのC#で行っているのと同じ操作を実行する方法を提供します。

@Gumboの答えは、nullをチェックする最良の方法を提供します。しかし、それはの違いに注意することが重要です=====JavaScriptでの、特にそれがためにチェックの問題に来るときundefined、および/またはnull

ここに2つの用語の違いについての本当に良い記事があります。基本的に、の==代わりにを使用した場合===、JavaScriptは比較している値を合体させ、この合体の比較結果を返すことを理解してください。


その記事(およびJash)について私を悩ませたのは、未定義のwindow.helloプロパティが何らかの理由でnullと評価されていることです。代わりに未定義にする必要があります。Firefoxエラーコンソールを試して、自分の目で確かめてください。
Ates Goral

3

Reactのcreate-react-appツールチェーンは、バージョン3.3.0(リリース5.12.2019)以降、null結合をサポートしていることに注意してください。リリースノートから:

オプションの連鎖演算子と無効な結合演算子

オプションの連鎖演算子と無効な合体演算子をサポートします!

// Optional chaining
a?.(); // undefined if `a` is null/undefined
b?.c; // undefined if `b` is null/undefined

// Nullish coalescing
undefined ?? 'some other default'; // result: 'some other default'
null ?? 'some other default'; // result: 'some other default'
'' ?? 'some other default'; // result: ''
0 ?? 300; // result: 0
false ?? true; // result: false

create-react-appつまり、3.3.0以降を使用している場合は、Reactアプリですでにnull-coalesceオペレーターの使用を開始できます。


3

はい、その提案は現在ステージ4です。これは、提案が正式なECMAScript標準に含める準備ができていることを意味します。Chrome、Edge、Firefoxの最近のデスクトップバージョンではすでに使用できますが、この機能がブラウザー間の安定性に達するまでもう少し待つ必要があります。

次の例を見て、その動作を確認してください。

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = undefined;
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);

前の例は次と同等です:

const var1 = undefined;
const var2 = "fallback value";

const result = (var1 !== null && var1 !== undefined) ?
    var1 :
    var2;
console.log(`Nullish coalescing results in: ${result}`);

注意合体がnullishますない脅威falsy値道||オペレータがやった(それだけのためにチェックしundefinedたりnull、次のような値)、それゆえ以下のスニペットは動作します:

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = ""; // empty string
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);


TypeScriptユーザーの場合、TypeScript 3.7以降、この機能も利用できるようになりました。


2

2020年4月の時点で提案フェーズにあるため、Javascriptですぐに利用できるようになる予定です。ステータスの互換性とサポートについては、こちらで監視できます-https://developer.mozilla.org/en-US/docs/Web/ JavaScript /リファレンス/オペレーター/ Nullish_coalescing_operator

活字体を使用している人々のためには、使用することができますnullish合体オペレータから活字体3.7を

ドキュメントから-

この機能- ??演算子-は、nullまたはを処理するときにデフォルト値に「フォールバック」する方法と考えることができますundefined。次のようなコードを書くとき

let x = foo ?? bar();

これは、値fooが「存在する」ときに使用されると言う新しい方法です。それはだときnullundefined、計算bar()その場所インチ


0

正解です

JavaScriptに存在しますか? はい、そうです。 だが。現在、ステージ32020-02-06の時点でサポートされていません。以下のURLのリンクをたどり、「仕様」と「ブラウザの互換性」のヘッダーに移動して、それがどこにあるかについての詳細を確認してください。

引用元:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

nullish合体演算子(??)は、左側のオペランドがnullまたは未定義の場合に右側のオペランドを返し、それ以外の場合は左側のオペランドを返す論理演算子です。

論理OR(||)演算子とは異なり、nullでも未定義でもない偽の値の場合、左のオペランドが返されます。言い換えれば、|| 別の変数fooにいくつかのデフォルト値を提供するために、いくつかの偽の値を使用可能であると考えると(例えば、 ''または0)、予期しない動作が発生する可能性があります。その他の例については、以下を参照してください。

例が必要ですか?私が投稿したリンクをたどってください、それはすべてを持っています。



MDNリンクは役に立ちますが、これは重複した答えです。代わりに、ヴォーンの答えの下でコメントしてください。
クリス

@Chris彼の答えは十分ではないので、私の答えです。
カールモリソン

0

現在では、Chrome、Edge、Firefox、Safariなどの主要なブラウザの最新バージョンで完全にサポートされています。null演算子とNullish Coalescing演算子の比較は次のとおりです

const response = {
        settings: {
            nullValue: null,
            height: 400,
            animationDuration: 0,
            headerText: '',
            showSplashScreen: false
        }
    };
    /* OR Operator */
    const undefinedValue = response.settings.undefinedValue || 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue || 'Default Value'; // 'Default Value'
    const headerText = response.settings.headerText || 'Hello, world!'; //  'Hello, world!'
    const animationDuration = response.settings.animationDuration || 300; //  300
    const showSplashScreen = response.settings.showSplashScreen || true; //  true
    /* Nullish Coalescing Operator */
    const undefinedValue = response.settings.undefinedValue ?? 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue ?? ''Default Value'; // 'Default Value'
    const headerText = response.settings.headerText ?? 'Hello, world!'; // ''
    const animationDuration = response.settings.animationDuration ?? 300; // 0
    const showSplashScreen = response.settings.showSplashScreen ?? true; //  false
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.