メモログ

⛰ 塵が積もって山とならないメモのログ 👄

Optional chaining and Nullish coalescing

ES2020で新しく追加された機能(ECMAScript 2016+ compatibility tableの画面の下の方にある)はどれもわりと実用的で、なくても大丈夫なんだけどあると便利といったものが並んでいる。Bigintは日常的には使わないとは思うけど。

その中で、Nullish coalescingOptional chaining はかなり便利。なくても大丈夫だし、使わなくても良いんだけど、便利だから日常的に書かれるJavaScriptの書き方を変えるものになると思う。

まず、Nullishとは何かというと、値がnullかundefinedになるものを言う。Falsyの場合、数値の0とかNaN、空文字列などが含まれるけど、Nullishは値が存在しない場合(nullとundefined)だけを扱う。

論理演算子の&&||論理演算子)は、Falsyな値ははすべてFalseとして扱うので、

const foo = 0;
const bar = foo || 100;

としたとき、0のようなFalsyな値をbarに渡したい場合でも、||の右側の値が使われてしまう。こういったときに従来なら

const foo = 0;
const bar = (typeof foo === "undefined" || foo === null) ? 100 : foo;

みたいな感じにしないといけなかった。(Strictモードならundefinedが別の値になることはないので、foo === undefinedと書いても大丈夫)。

Nullish coalescingならundefinedかnullの場合だけ扱うようになるので、以下のように簡単に書く事ができる。

const foo = 0;
const bar = foo ?? 100;

これは便利。


Optional chainingは、.演算子でオブジェクトのプロパティにアクセスするときに、良い感じにしてくれる。

例えば以下のようなオブジェクトがあった場合で、foo.bar.bazの値にアクセスしたいとする。

const foo = {
  bar: {
    baz: 'qux'
  }
};
console.log(foo.bar.baz);

オブジェクト内に中間(bar)のプロパティが必ず存在する場合は問題ないけど、foo.bar が undefined である可能性があると、foo.bar.bazのアクセスのときにTypeErrorになる可能性がある。undefinedやnullに対して.演算子でプロパティにアクセスするとTypeErrorとなる。

なので、そういった場合、従来

console.log(foo.bar && foo.bar.baz);

みたいな感じにして、barのプロパティにアクセスする前にbarが存在するかを確認しないといけなかった。上の例の場合、&&演算子によって、foo.bar が Falsy の場合はfoo.bar.bazの評価はされずfoo.bar の値が返る。Falsyな場合なので、foo.bar に0が入ってると、0が返ってくる。それで困ることは実用上まずないと思うけど、上の方法はundefinedが返ってくることは保証されない。

Optional chainingを使うと、以下のように書ける。

console.log(foo.bar?.baz);

この場合、barがNullsih(undefinedかnull)であった場合、bazの評価はしないで undefined が返ってくる。便利。

連結して使う事ができるので、

console.log(foo?.bar?.baz);

みたいにfooがundefinedの可能性がある場合でも、安全にプロパティにアクセスすることができる。foo && foo.bar && foo.bar.bazとか書かなくて良い。これは、本当に、便利。


Nullish coalescingもOptional chainingも新しい機能であるので、機能に対応していないブラウザではSyntaxErrorになってしまう。

でもTypeScriptの3.7でこれらの機能に対応している(TypeScript 3.7)。ので、TypeScript 3.7 を使っていれば、安全に使える状態にある。Babel 7 でも大丈夫みたい。